local

package
v0.2.8 Latest Latest
Warning

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

Go to latest
Published: Aug 17, 2026 License: AGPL-3.0 Imports: 20 Imported by: 0

Documentation

Overview

Local-subprocess implementation of GetHostByID + OpenInternalConn.

In local mode the daemon and the spawned clank-host (and any dev servers it forks) all run on the same machine. The "internal" network is just loopback — port `port` lives at 127.0.0.1:<port> regardless of what URL clank-host's HTTP listener is on.

Note that c.url is clank-host's own listener URL (the HTTP control plane), not the per-worktree dev-server port the caller wants. The dev server (Metro, etc.) binds an OS-allocated port that nobody outside the preview manager knows in advance — the caller passes it in via the `port` arg here. So even though we have a URL on the child record, we ignore its host and dial 127.0.0.1 explicitly.

This also makes the local provisioner a useful test substrate for previewtunnel.RoundTripper: stand up an httptest server, dial through OpenInternalConn, and you've exercised the full Provisioner.OpenInternalConn → http.Transport → upstream chain without needing a real cloud provider.

Package local implements provisioner.Provisioner by spawning a clank-host subprocess on the local machine. Laptop-mode counterpart to flysprites / flymachines: same Provisioner interface, same HostRef shape, different "compute" — a child process bound to a random localhost port instead of a remote sandbox.

EnsureHost is idempotent within a daemon lifetime: the first call spawns clank-host, subsequent calls return the cached HostRef. Subprocesses don't survive daemon restarts — cross-restart persistence is the cloud provisioners' job. SuspendHost is a no-op; DestroyHost kills the child.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Options

type Options struct {
	// BinPath is the absolute path to the clank-host binary. Empty
	// → resolved via PATH at first EnsureHost.
	BinPath string

	// DataDir is passed to clank-host as --data-dir for its host.db.
	// Empty → clank-host uses its own default ($HOME/.clank-host).
	DataDir string

	// WorkRoot is passed to clank-host as --work-root — the parent for
	// worktrees and repo canonicals. Empty → clank-host uses its own
	// default ($HOME/work, the dedicated-sandbox layout). Laptop
	// deployments set this under the user's clank config dir so the
	// host doesn't drop a work/ directory into their home.
	WorkRoot string

	// ProvisionTimeout caps how long EnsureHost waits for the child
	// to print its bound listen address. Default: 10 seconds.
	ProvisionTimeout time.Duration

	// NotifierWebhookURL, when non-empty, configures the subprocess
	// clank-host to POST agent-lifecycle notifications back to this
	// URL — typically the same clankd that spawned it. Empty disables
	// the notifier (laptop dev without push delivery).
	NotifierWebhookURL string

	// PreviewWebhookURL, when non-empty, configures the subprocess
	// clank-host to POST preview register/revoke webhooks back to
	// this URL on the gateway. Same auth as NotifierWebhookURL (the
	// per-host bearer below). When set without NotifierWebhookURL,
	// the bearer is still generated and passed so the preview
	// webhook can authenticate.
	PreviewWebhookURL string

	// UserID is the identity the local provisioner reports for its
	// single in-memory host record. Must match the `sub` claim the
	// gateway's authenticator extracts from inbound JWTs, otherwise
	// the preview surface's owner-ship check rejects owner_only
	// tokens as cross-tenant. Empty falls back to "local".
	UserID string

	// TunnelInternalConn routes OpenInternalConn through clank-host's
	// /tunnel endpoint (pkg/provisioner/tunnelclient) instead of
	// dialing 127.0.0.1 directly — the same data path machine-style
	// cloud backends use. Off for laptop speed; turn on (e.g. in the
	// docker dev stack) to exercise the production preview path
	// end-to-end without a cloud provider.
	TunnelInternalConn bool

	// Templates is the builtin create-project catalog, forwarded to the
	// subprocess as --templates-json (the builtin half of its GET
	// /templates). Passed as an explicit flag so it beats any
	// CLANK_TEMPLATES the child would inherit from this process's env.
	// Empty passes no flag — clank-host then serves only the user's
	// own GitHub template repos.
	Templates []provisioner.Template
}

Options configures the local-subprocess provisioner.

type Provisioner

type Provisioner struct {
	// contains filtered or unexported fields
}

Provisioner manages a single persistent clank-host subprocess.

func New

func New(opts Options, lg *log.Logger) *Provisioner

New constructs a Provisioner. log may be nil.

func (*Provisioner) DestroyHost

func (p *Provisioner) DestroyHost(_ context.Context, _ string) error

DestroyHost kills the subprocess and clears the cache.

func (*Provisioner) DestroyHostsByUser

func (p *Provisioner) DestroyHostsByUser(ctx context.Context, _ string) error

DestroyHostsByUser kills the single subprocess this provider manages. userID is ignored (the local provisioner serves one user), mirroring EnsureHost. Idempotent: a no-op when no child is running.

func (*Provisioner) EnsureHost

func (p *Provisioner) EnsureHost(_ context.Context, _ string) (provisioner.HostRef, error)

EnsureHost implements provisioner.Provisioner. Returns the cached HostRef when the child is healthy, otherwise spawns a fresh one.

userID is accepted for interface symmetry with flysprites/flymachines but is ignored — the local provisioner serves a single user. Multi- tenant routing is PR 4.

func (*Provisioner) GetHostByID

func (p *Provisioner) GetHostByID(_ context.Context, hostID string) (provisioner.HostRef, error)

GetHostByID returns the cached HostRef when the running child's hostID matches; otherwise reports the host as missing.

The local provisioner only ever holds one child (one user), so any non-matching hostID is by definition not on this host. Mirrors the EnsureHost contract: we don't spawn a new child on a lookup.

func (*Provisioner) GetHostByNotifierToken

func (p *Provisioner) GetHostByNotifierToken(_ context.Context, notifierToken string) (hoststore.Host, error)

GetHostByNotifierToken implements gateway.PreviewHostLookup (and notify.HostLookup): given a notifier_token bearer presented by a webhook caller, return the matching host row.

In local mode the row isn't in Postgres — it's in p.current. The preview webhook flow (clank-host → POST /webhooks/preview/register) uses this lookup to authenticate the inbound bearer.

func (*Provisioner) OpenInternalConn

func (p *Provisioner) OpenInternalConn(ctx context.Context, hostID string, port int) (net.Conn, error)

OpenInternalConn dials 127.0.0.1:<port> directly — or, with Options.TunnelInternalConn, through clank-host's /tunnel endpoint like the machine-style cloud backends. hostID must match the currently-running child so we don't paper over a stale ref pointing at a different machine state.

func (*Provisioner) Stop

func (p *Provisioner) Stop()

Stop kills the subprocess if running. Safe to defer.

func (*Provisioner) SuspendHost

func (p *Provisioner) SuspendHost(context.Context, string) error

SuspendHost is a no-op: subprocesses don't auto-suspend.

Jump to

Keyboard shortcuts

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