Skip to content

feat(sdk/go): Go SDK with full API parity (#568)#587

Open
khrees wants to merge 15 commits intosuperradcompany:mainfrom
khrees:feat/go-sdk
Open

feat(sdk/go): Go SDK with full API parity (#568)#587
khrees wants to merge 15 commits intosuperradcompany:mainfrom
khrees:feat/go-sdk

Conversation

@khrees
Copy link
Copy Markdown

@khrees khrees commented Apr 20, 2026

Closes #568

Summary

Full Go SDK for microsandbox, implemented via CGO over a new sdk/go-ffi Rust cdylib. The library is loaded at runtime via dlopen/dlsym — no build-time linking required. API design follows Go conventions (functional options, context-first, typed errors) while covering the same surface as the Node and Python SDKs.

What's included

Sandbox lifecycle

  • CreateSandbox / CreateSandboxDetached, GetSandbox, StartSandbox, StartSandboxDetached, ListSandboxes, RemoveSandbox
  • SandboxHandle — lightweight DB record reference with Connect, Start, Stop, Kill, Remove, Metrics
  • Live SandboxStop, StopAndWait, Kill, Wait, Drain, Detach, Close, OwnsLifecycle, RemovePersisted
  • Attach / AttachShell for interactive PTY sessions
  • AllSandboxMetrics, Sandbox.MetricsStream(interval)

Exec

  • Exec / Shell — collected output
  • ExecStream / ShellStream — streaming with ExecHandle.Recv, Collect, Wait, Kill, Signal, ID, TakeStdin
  • Per-exec User and Env overrides via WithExecUser / WithExecEnv

Filesystem

  • SandboxFsRead, Write, List, Stat, CopyFromHost, CopyToHost, Mkdir, Remove, RemoveDir, Copy, Rename, Exists
  • Streaming: ReadStream (io.WriterTo) and WriteStream (io.Writer)

Volumes

  • CreateVolume, GetVolume, ListVolumes, RemoveVolume
  • Volume.Path() / Volume.FS() and VolumeHandle with full metadata + FS()
  • VolumeFs — direct host-side file ops on the volume directory

Options & factories

  • NetworkPolicy.None/PublicOnly/AllowAll, custom rules
  • Secret.Env(...) for proxy-layer credential injection
  • Patch.Text/Append/Mkdir/Remove/Symlink/CopyFile/CopyDir
  • Mount.Bind/Named/Tmpfs with WithMounts
  • WithHostname, WithUser, WithReplace on sandbox creation

FFI layer (sdk/go-ffi/)

  • New Rust cdylib exposing extern "C" async wrappers with an internal Tokio runtime
  • Handle registry pattern (opaque u64 keys) for sandbox, exec, metrics stream, fs read/write handles
  • JSON over FFI boundary; cancel via shared AtomicBool keyed by cancel ID

Test plan

  • go build ./... — passes
  • go vet ./... — passes
  • Integration tests in sdk/go/*_test.go against a running microsandbox daemon
  • Verify EnsureInstalled downloads and loads the cdylib correctly on a fresh machine
  • Test detached sandbox survives Go process exit and reattaches via GetSandbox

khrees added 15 commits April 17, 2026 15:04
Introduces a Go client SDK for microsandbox under sdk/go/.

- sandbox.go: NewSandbox, NewSandboxDetached, GetSandbox, ListSandboxes,
  RemoveSandbox, Stop, Kill, Detach, StopAndWait, FS(), Metrics,
  AllSandboxMetrics
- exec.go: Exec, Shell, ExecStream with streaming ExecEvent channel
- fs.go: SandboxFs with Read/Write/ReadString/WriteString/List/Stat/CopyIn/CopyOut
- volume.go: NewVolume, ListVolumes, RemoveVolume, GetVolume, VolumeExists
- options.go: full functional-options API — image, memory, CPUs, env,
  workdir, volumes, network policy, secrets, patches, ports, scripts
- errors.go: typed ErrorKind with IsKind/IsSandboxNotFound/IsExecTimeout/IsExecFailed helpers
- internal/ffi: FFI interface + MockFFI test double + RealFFI stub
  (real CGO wiring deferred to the go-ffi Rust crate)
Add the `microsandbox-go-ffi` crate to expose the Rust API over a
stable C-ABI. This allows the Go SDK to interact with the runtime
via CGO.

Refactor `sdk/go` to consume the new FFI layer:
- Replace the mock FFI interface with real CGO bindings.
- Update error handling to parse JSON error payloads from Rust.
- Align Go types and options with the FFI contract.
- Remove `sdk/go/internal/ffi/mock.go`.
Introduce comprehensive test coverage for the Go SDK including:
- Unit tests for error handling, exec output, filesystem entries, and
  options.
- Integration tests for sandbox lifecycle, command execution, filesystem
  operations, metrics, and volume management.
- A Makefile with targets to build the Rust FFI and run both unit and
  integration tests.
Configure cbindgen to automatically generate C headers for the
Go FFI crate. Expand SandboxOptions to support detached mode,
port mapping, network policies, secrets, and filesystem patches.
Update FFI function signatures to accept cancellation IDs and
add support for streaming exec events.
Expose `msb_sandbox_detach` in the FFI layer to allow releasing
handles without terminating the VM. Wrap the new function in the
Go Sandbox struct.

Include new example programs covering basic usage, secrets,
streaming exec, and volumes. Adjust metrics test timing to account
for sampler initialization.
- Add `EnsureInstalled` function to the Go SDK to manage the installation of the microsandbox runtime, including the Go FFI shared library.
- Update examples to call `EnsureInstalled` at startup, ensuring the runtime is available before executing any SDK functions.
- Introduce error handling for library loading failures with a new `ErrLibraryNotLoaded` error type.
- Remove the Makefile from the Go SDK as it is no longer needed for building the FFI.
- Update documentation to reflect changes in installation and usage patterns.
- Introduce a new README.md file for the Go SDK, detailing the features, requirements, installation instructions, and quick start examples for using the microsandbox.
- Include sections on command execution, streaming execution, filesystem operations, named volumes, network policies, DNS filtering, port publishing, and secrets management.
- Provide code snippets to illustrate usage patterns and enhance developer understanding of the SDK capabilities.
- Add ExecHandle.ID(), Collect(), Wait(), Kill() to public exec API
- Add Volume.Path(), Volume.FS(), VolumeHandle.Path(), VolumeHandle.FS()
- Add VolumeFs type for direct host-side file ops on volume directories
- Add MountConfig, Mount factory (Bind/Named/Tmpfs), WithMounts option
- Wire Volumes through SandboxConfig and CreateSandbox → FFI
- Add AllSandboxMetrics, SandboxHandle.Metrics, Sandbox.RemovePersisted
- Add MetricsStream(interval) with MetricsStreamHandle
- Add SandboxFs.ReadStream / WriteStream with FsReadStream / FsWriteStream
- Add VolumeHandle.Path from msb_volume_get JSON response
- Add corresponding Rust FFI functions in go-ffi/src/lib.rs
Replace the raw C.uint64_t handle with atomic.Uint64 to enable safe
concurrent Close/Detach calls. Add best-effort handle recovery and
cleanup
when JSON unmarshalling fails during sandbox creation, preventing
Rust-side
leaks. Map context.Canceled and context.DeadlineExceeded to ErrCancelled
in wrapFFI, preserving the original error as Cause. Update documentation
to clarify that Volume.Path is empty for CreateVolume/ListVolumes
results.
Simplify Error.Error() to omit redundant Kind prefix and handle edge
cases (empty message, cause-only). Rename TlsConfig to TLSConfig for
idiomatic Go naming. Fix error message casing in examples.
@appcypher
Copy link
Copy Markdown
Member

Bro. Thanks for contributing this. I already took a look at it a couple days back.
I will do a more thorough review over the weekend.

@toksdotdev
Copy link
Copy Markdown
Member

toksdotdev commented Apr 28, 2026

@Khrees2412 is the Go implementation auto-generated? or just the ffi.go?

asking in order to guage how much work it'd be to maintain.

@khrees
Copy link
Copy Markdown
Author

khrees commented May 5, 2026

@toksdotdev

Mostly handwritten. ffi.go is the only really low-level FFI bridge layer; the rest of the Go SDK is normal handwritten Go.

Claude helped a lot with the initial implementation, but it’s not codegen-driven. Maintenance should mostly just be keeping ffi.go in sync with Rust FFI changes, plus the usual wrapper/test updates when the API changes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat: Go SDK

3 participants