buildworker

package module
v0.0.0-...-3726433 Latest Latest
Warning

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

Go to latest
Published: Aug 14, 2026 License: MIT Imports: 21 Imported by: 0

README

Plumtree Build Worker

Sandboxed service that compiles uploaded Go app source into WASM artifacts.

Owns:

  • isolated build execution.
  • source size and build-time limits.
  • module cache isolation.
  • checksum/module policy enforcement.
  • build logs.
  • WASM artifact output.

Does not own:

  • app metadata authority.
  • runtime session execution.
  • SSH connections.

Documentation

Overview

Package buildworker compiles uploaded Go app source into WASM artifacts inside a constrained, network-free sandbox. The control plane never trusts the source: the worker enforces source-size, file-count, build-time, module policy, and cache-isolation limits, and returns either a content-addressed artifact or a structured build failure.

Index

Constants

This section is empty.

Variables

View Source
var DefaultAllowedModules = []string{
	"github.com/Ceinl/plumtree/sdk",
	"golang.org/x/sys",
	"golang.org/x/text",
}

DefaultAllowedModules is the v1 module allowlist: the standard library (implicit, never in go.mod), and the Plumtree SDK. Apps may only require modules whose path is, or sits beneath, one of these.

Functions

func PackSource

func PackSource(proj string) ([]byte, error)

PackSource builds a deterministic tar archive of an app project for upload to the build worker. Only sourceRoots are included; file order is sorted so the archive bytes are reproducible for a given tree.

func SourceDigest

func SourceDigest(archive []byte) string

SourceDigest returns the content address of a packed source archive.

Types

type Builder

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

Builder compiles source archives to WASM under a fixed Config.

func NewBuilder

func NewBuilder(cfg Config) *Builder

NewBuilder returns a Builder with defaults filled in for any zero Config field.

func (*Builder) Build

func (b *Builder) Build(ctx context.Context, req Request) (Result, error)

Build compiles req.Source to a WASM artifact inside a fresh sandbox. A build that fails for an author-caused reason (oversized source, disallowed module, compile error, timeout) returns Result{Success:false, Failure:...} with a nil error; a nil error means the worker itself functioned. A non-nil error means the worker could not run the build at all.

type Client

type Client struct {
	BaseURL string
	Token   string
	HTTP    *http.Client
}

Client calls a remote build Service. The control plane uses it to compile uploaded source without hosting the toolchain in its own process.

func NewClient

func NewClient(baseURL, token string) *Client

NewClient returns a Client with a default timeout sized for cold builds.

func (*Client) Build

func (c *Client) Build(ctx context.Context, req Request) (Result, error)

Build sends a build request and returns the structured Result. A non-nil error indicates a transport or worker-internal failure; an author-caused build failure arrives as Result.Failure with a nil error.

type Config

type Config struct {
	// GoBin is the go toolchain binary. Defaults to "go" resolved on PATH.
	GoBin string
	// WorkRoot is the parent directory for per-build sandboxes. Defaults to the
	// OS temp dir. Each build gets an isolated subdirectory removed afterwards.
	WorkRoot string
	// MaxSourceBytes caps the uploaded archive size. Default 8 MiB.
	MaxSourceBytes int64
	// MaxExtractBytes caps total extracted source bytes. Default 64 MiB.
	MaxExtractBytes int64
	// MaxFiles caps the number of files in the archive. Default 2000.
	MaxFiles int
	// MaxMemoryBytes caps the build process's address space (RLIMIT_AS) on
	// supported platforms (Linux). Default 2 GiB. 0 after defaults disables it.
	MaxMemoryBytes int64
	// Timeout bounds total build wall-clock time. Default 90s.
	Timeout time.Duration
	// GoProxy sets GOPROXY for the build. Default "off" — no network. Set to a
	// trusted module mirror to allow restricted dependency resolution.
	GoProxy string
	// AllowedModules is the module path allowlist (see enforceModulePolicy).
	// Defaults to DefaultAllowedModules. Set to a non-nil empty slice to skip
	// the check (used for std-only test programs).
	AllowedModules []string
	// WorkspaceModules are local module directories (e.g. an unpublished SDK and
	// TUI runtime) tied into a generated go.work alongside the uploaded source so
	// the build resolves them without a published version. They may come from a
	// development checkout or from assets bundled with the worker. GoProxy must
	// resolve any transitive dependencies, either through a trusted remote mirror
	// or a bundled file proxy.
	WorkspaceModules []string
	// ExtraEnv is appended to the hermetic build environment.
	ExtraEnv []string
}

Config bounds a Builder. Zero fields fall back to the defaults applied by NewBuilder, so callers can override only what they care about.

type Failure

type Failure struct {
	Stage   Stage  `json:"stage"`
	Message string `json:"message"`
	Log     string `json:"log,omitempty"`
}

Failure is a structured, author-facing build error.

func (*Failure) Error

func (f *Failure) Error() string

type Request

type Request struct {
	// Source is the tar archive produced by PackSource.
	Source []byte `json:"source"`
	// ABIVersion is recorded on the resulting artifact metadata.
	ABIVersion uint8 `json:"abiVersion"`
}

Request is one build job. Source marshals to base64 over JSON.

type Result

type Result struct {
	Success         bool     `json:"success"`
	WASM            []byte   `json:"wasm,omitempty"`
	Digest          string   `json:"digest,omitempty"` // sha256:... content address of WASM
	SizeBytes       int64    `json:"sizeBytes,omitempty"`
	ABIVersion      uint8    `json:"abiVersion"`
	CompilerVersion string   `json:"compilerVersion,omitempty"`
	BuildLog        string   `json:"buildLog,omitempty"`
	DurationMillis  int64    `json:"durationMillis"`
	Failure         *Failure `json:"failure,omitempty"`
}

Result is the outcome of a build. Exactly one of Failure / (WASM,Digest) is meaningful depending on Success.

type Service

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

Service is the HTTP front for a Builder. It runs as its own process, separate from the control plane, so untrusted compilation never shares an address space with app metadata, auth state, or secrets.

func NewService

func NewService(builder *Builder, token string) *Service

NewService wraps a Builder. An empty token disables auth (local/dev use).

func NewServiceWithLimits

func NewServiceWithLimits(builder *Builder, token string, maxConcurrent, maxQueued int) *Service

NewServiceWithLimits wraps a Builder with bounded build admission. At most maxConcurrent builds execute and maxQueued additional requests wait. A zero queue rejects immediately when all workers are busy.

func (*Service) Handler

func (s *Service) Handler() http.Handler

Handler returns the service's HTTP routes.

type Stage

type Stage string

Stage labels where in the pipeline a build failed, so pt deploy can present a useful message without parsing logs.

const (
	StageSource  Stage = "source"  // archive too large / malformed / path escape
	StagePolicy  Stage = "policy"  // module allowlist or toolchain rejection
	StageCompile Stage = "compile" // go build returned a non-zero status
	StageTimeout Stage = "timeout" // build exceeded the wall-clock budget
	StageWorker  Stage = "worker"  // internal worker error (not the author's fault)
)

Directories

Path Synopsis
cmd
build-worker command
Command build-worker runs the sandboxed source-to-WASM build service as its own process, separate from the control plane.
Command build-worker runs the sandboxed source-to-WASM build service as its own process, separate from the control plane.

Jump to

Keyboard shortcuts

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