facet

package module
v0.1.0 Latest Latest
Warning

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

Go to latest
Published: Aug 26, 2026 License: MIT Imports: 23 Imported by: 0

README

wago-facet

wago-facet is the reference Wago plugin for Facet.

Facet is a small system interface for Core WebAssembly. The import module is "facet".

This repository follows Facet 0.1.

Status

Version 0.1.0 is the experimental reference release for Facet 0.1.

The Runtime plugin path implements the canonical Facet 0.1 import surface. The inventory test requires exactly 261 Facet imports with no duplicate names. Wago's normal registration check verifies scalar ABI categories, and the required instantiation interceptor additionally verifies Facet's structural GC-reference signatures before guest code starts.

Wago callback-scoped guest-storage APIs provide the representation-sensitive operations that Facet needs:

  • Memory32 and Memory64 by exact WebAssembly memory index;
  • multi-memory guest buffers and iovecs;
  • numeric and v128 Wasm GC arrays;
  • nested GC arrays for scatter/gather I/O;
  • exact caller-defined GC types;
  • caller-typed GC array result allocation;
  • zero-copy mutable GC-array payload access.

GC references remain opaque Wago tokens. wago-facet does not interpret collector references or object pointers. It resolves them only through Wago's callback-scoped guest-storage APIs.

The preferred integration is Provider() through Wago's plugin system. The plugin requires Wago's instance.instantiate.intercept authority so a module with a non-canonical structural Facet import is rejected during instantiation. Caller-allocated string and readlink results remain templates: the importing module selects a concrete nullable array type with the required element storage class.

Implemented surface

The Runtime plugin path includes:

  • ABI version, process exit, yield, and opaque resource lifecycle;
  • stdin, stdout, and stderr descriptors;
  • arguments and environment for UTF-8, UTF-16, and UTF-32;
  • strict and WTF text handling;
  • system and monotonic clocks;
  • cryptographic randomness;
  • preopens, descriptor metadata, seek/tell, synchronization, and sizing;
  • sequential, positional, and vectored I/O;
  • Memory32, Memory64, and GC-array buffer families;
  • directory iteration and rewind;
  • capability-beneath path operations;
  • hard links, symbolic links, and readlink;
  • IPv4 and IPv6 socket lifecycle operations;
  • stream and datagram I/O;
  • DNS resolution;
  • level-triggered polling and monotonic timers;
  • caller-typed allocating GC string and readlink results.

Facet uses normal Core WebAssembly linking for feature detection. The plugin does not substitute memory 0 for another memory index and does not copy GC arrays through a hidden linear-memory scratch area.

Conformance

wago-facet runs the normative Facet 0.1 suite from a pinned facet-spec revision on both Linux/amd64 and Linux/arm64.

The current gate is:

137 / 137 standard WAST tests   PASS
  6 /   6 harness tests         PASS
143 / 143 total tests           PASS
0 failures
0 crashes
0 timeouts

CI runs the complete gate with the default collector. It also reruns all 137 standard WAST cases with forced moving-nursery collection on every GC allocation. A differential integration test compares the same argument transfer through Memory32, Memory64, and a Wasm GC array.

Each standard WAST file runs in an isolated subprocess. A runtime crash or timeout is therefore reported as a conformance failure instead of terminating the complete test run.

The six harness tests cover behavior outside standard WAST command composition:

  • cross-instance handle isolation;
  • process exit status;
  • stdout and stderr validation;
  • null nested-GC child validation before I/O;
  • TCP loopback interaction;
  • UDP loopback interaction.

See tests/conformance/README.md for the pinned-suite and local-run instructions.

Installation

The release can be consumed as a Go module:

go get github.com/jtenner/wago-facet@v0.1.0

Provider() is the preferred Wago plugin integration.

Supported platforms

Version 0.1.0 supports:

  • Linux amd64;
  • Linux arm64.

The package intentionally uses Linux capability-beneath filesystem operations, polling, and socket primitives. It is not currently a portable Darwin or Windows implementation. Unsupported operating systems are outside the advertised compatibility contract for this release.

Plugin configuration

A plugin selection can configure streams, environment entries, preopens, and the maximum number of live resource handles.

Example:

{
  "stdin": "inherit",
  "stdout": "inherit",
  "stderr": "inherit",
  "env": ["MODE=development"],
  "preopens": [
    {
      "guest": "~",
      "host": "/srv/my-guest",
      "rights": ["stat", "dir-iterate"]
    }
  ],
  "maxHandles": 1024
}

The ~ name has no special ABI behavior. It is an ordinary Facet preopen display name.

If rights is omitted, a preopen receives stat, path-open, and dir-iterate rights. An explicit "rights": [] grants zero Facet rights.

Guest capabilities

Every import declares a Wago guest capability. Important capability names include:

facet.arguments.read
facet.environment.read
facet.clock.read
facet.random.read
facet.process.exit
facet.stdio.read
facet.stdio.write
facet.fd.manage
facet.fd.read
facet.fd.write
facet.filesystem.read
facet.filesystem.write
facet.filesystem.open
facet.network
facet.poll

An embedder can deny these capabilities through normal Wago policy.

Direct low-level use

Provider() is the complete and preferred integration.

Low-level embedders that need only the scalar/resource subset can call NewInstanceImports(Config). The returned InstanceImports owns the import map and all backing host descriptors. Call Close after the guest instance is finished. There is intentionally no ownership-free Imports(Config) helper because such an API cannot safely release guest-created resources or pinned preopen descriptors.

Development

Run the normal Go checks with:

go test ./...
go test -race ./...
go vet ./...

The ordinary test suite includes seed corpora for text-codec and plugin-configuration fuzz targets. CI also verifies Go 1.22 compatibility.

Run the complete Facet 0.1 conformance gate with the pinned suite as described in tests/conformance/README.md.

CI pins both the Wago revision used by the plugin and the Facet specification revision used by conformance testing.

Runtime integration

See docs/wago-runtime-gaps.md for the Wago guest-storage requirements that enabled the complete Facet representation model and the remaining design rules that the plugin relies on.

License

MIT

Documentation

Overview

Package facet implements the Facet 0.1 system interface as an explicit Wago plugin. It exposes only imports that current Wago can implement exactly.

Index

Constants

View Source
const (
	ErrOK                 int32 = 0
	ErrPermission         int32 = 1
	ErrNoEntry            int32 = 2
	ErrIO                 int32 = 3
	ErrBadHandle          int32 = 4
	ErrAgain              int32 = 5
	ErrNoMemory           int32 = 6
	ErrAccess             int32 = 7
	ErrBusy               int32 = 8
	ErrExists             int32 = 9
	ErrNotDirectory       int32 = 10
	ErrIsDirectory        int32 = 11
	ErrInvalid            int32 = 12
	ErrFileTooLarge       int32 = 13
	ErrNoSpace            int32 = 14
	ErrReadOnly           int32 = 15
	ErrPipe               int32 = 16
	ErrRange              int32 = 17
	ErrNotEmpty           int32 = 18
	ErrLoop               int32 = 19
	ErrNameTooLong        int32 = 20
	ErrNotSupported       int32 = 21
	ErrOverflow           int32 = 22
	ErrIllegalSequence    int32 = 23
	ErrFault              int32 = 24
	ErrType               int32 = 25
	ErrQuota              int32 = 26
	ErrCanceled           int32 = 27
	ErrAddressInUse       int32 = 28
	ErrAddressInvalid     int32 = 29
	ErrConnectionRefused  int32 = 30
	ErrConnectionReset    int32 = 31
	ErrNotConnected       int32 = 32
	ErrTimedOut           int32 = 33
	ErrHostUnreachable    int32 = 34
	ErrNetworkUnreachable int32 = 35
	ErrProtocol           int32 = 36
	ErrCapability         int32 = 37
	ErrEnd                int32 = 38
	ErrOther              int32 = 255
)
View Source
const (
	RightRead uint64 = 1 << iota
	RightWrite
	RightSeek
	RightTell
	RightStat
	RightSetSize
	RightSync
)
View Source
const (
	RightPathOpen uint64 = 1 << (16 + iota)
	RightPathCreate
	RightPathRemove
	RightPathRename
	RightPathLink
	RightPathSymlink
	RightPathReadlink
	RightDirIterate
)
View Source
const (
	FileTypeUnknown int32 = iota
	FileTypeRegular
	FileTypeDirectory
	FileTypeSymlink
	FileTypeChar
	FileTypeBlock
	FileTypeSocket
	FileTypeFIFO
)
View Source
const (
	FDAppend   uint32 = 1 << 0
	FDNonblock uint32 = 1 << 1
)
View Source
const (
	OpenCreate uint32 = 1 << iota
	OpenExclusive
	OpenTruncate
	OpenDirectory
	OpenNoFollow
	OpenAppend
	OpenNonblock
)
View Source
const (
	RemoveFile uint32 = 1 << iota
	RemoveDirectory
)
View Source
const (
	RenameReplace uint32 = 1 << iota
	RenameNoReplace
	RenameExchange
)
View Source
const (
	SeekSet int32 = iota
	SeekCur
	SeekEnd
)
View Source
const (
	StatHasATime uint32 = 1 << iota
	StatHasMTime
	StatHasCTime
)
View Source
const (
	AFUnspec int32 = iota
	AFInet4
	AFInet6
)
View Source
const (
	SockStream int32 = 1
	SockDgram  int32 = 2
)
View Source
const (
	ProtoDefault int32 = iota
	ProtoTCP
	ProtoUDP
)
View Source
const (
	ShutRD int32 = 1 + iota
	ShutWR
	ShutRDWR
)
View Source
const (
	PollReadable uint32 = 1 << iota
	PollWritable
	PollHangup
	PollError
	PollTimer
)
View Source
const (
	PollSourceFD int32 = 1 + iota
	PollSourceTimer
)
View Source
const (
	EnvName int32 = iota
	EnvValue
)
View Source
const (
	ID      = "github.com/jtenner/wago-facet"
	Module  = "facet"
	Version = "0.1.0"
)
View Source
const (
	CapCore            wago.Capability = "facet.core"
	CapArgumentsRead   wago.Capability = "facet.arguments.read"
	CapEnvironmentRead wago.Capability = "facet.environment.read"
	CapClockRead       wago.Capability = "facet.clock.read"
	CapRandomRead      wago.Capability = "facet.random.read"
	CapProcessExit     wago.Capability = "facet.process.exit"
	CapSchedulerYield  wago.Capability = "facet.scheduler.yield"
	CapStdinRead       wago.Capability = "facet.stdio.read"
	CapStdoutWrite     wago.Capability = "facet.stdio.write"
	CapFDManage        wago.Capability = "facet.fd.manage"
	CapFDRead          wago.Capability = "facet.fd.read"
	CapFDWrite         wago.Capability = "facet.fd.write"
	CapFilesystemRead  wago.Capability = "facet.filesystem.read"
	CapFilesystemWrite wago.Capability = "facet.filesystem.write"
	CapFilesystemOpen  wago.Capability = "facet.filesystem.open"
	CapNetwork         wago.Capability = "facet.network"
	CapPoll            wago.Capability = "facet.poll"
)
View Source
const PathFollowSymlink uint32 = 1 << 0
View Source
const SockNonblock uint32 = 1 << 0

Variables

This section is empty.

Functions

func ConfigSchema

func ConfigSchema() json.RawMessage

func Definition

func Definition() wago.PluginDefinition

func MarshalConfig

func MarshalConfig(cfg any) (json.RawMessage, error)

func Provider

func Provider() wago.PluginProvider

Types

type Config

type Config struct {
	Stdin          io.Reader
	Stdout, Stderr io.Writer
	Args           []string
	Env            []string
	Preopens       []Preopen
	MaxHandles     uint32
}

type InstanceImports

type InstanceImports struct {
	Imports wago.Imports
	// contains filtered or unexported fields
}

InstanceImports owns one low-level single-instance import map and every host resource that backs it. Close must be called when the guest instance is done. Provider remains the preferred integration because Wago drives its lifecycle.

func NewInstanceImports

func NewInstanceImports(cfg Config) (*InstanceImports, error)

NewInstanceImports creates a closable low-level Facet import bundle. Callback-scoped indexed-memory and GC-array imports remain Provider-only.

func (*InstanceImports) Close

func (i *InstanceImports) Close() error

Close releases all descriptors and other host resources owned by this bundle.

type Plugin

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

func (*Plugin) Register

func (p *Plugin) Register(reg *wago.Registrar) error

type Preopen

type Preopen struct {
	Guest  string
	Host   string
	Rights uint64
}

Directories

Path Synopsis
Package register exposes the Facet provider catalog to generated Wago runtimes.
Package register exposes the Facet provider catalog to generated Wago runtimes.

Jump to

Keyboard shortcuts

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