Documentation
¶
Index ¶
- Constants
- func CheckPolicy(def CommandDef, args []string) bool
- func CommandFromArgv0(argv0 string) string
- func EarlyReject(raw, command string, args []string) (string, bool)
- func EarlyRejectFromEnv(command string, args []string) (string, bool)
- func RunGitShim(args []string) (int, error)
- func ShellQuote(value string) string
- type BindMount
- type BoidExecutor
- type BoidOp
- type BoidRequest
- type Broker
- func (b *Broker) GetContext(token string) (TokenContext, bool)
- func (b *Broker) Handle(req *ExecRequest) *ExecResponse
- func (b *Broker) Register(commands map[string]CommandDef, builtinPolicies map[string]BuiltinPolicy, ...) string
- func (b *Broker) RegisterWithSecrets(commands map[string]CommandDef, builtinPolicies map[string]BuiltinPolicy, ...) string
- func (b *Broker) Start(ctx context.Context) error
- func (b *Broker) Stop()
- func (b *Broker) Unregister(token string)
- type BuiltinPolicy
- type CommandDef
- type ExecRequest
- type ExecResponse
- type FetchRequest
- type FileWrite
- type GitBinding
- type GitOp
- type GitRemote
- type GitRequest
- type GitUpstream
- type HarnessType
- type Mount
- type MountType
- type NFTRule
- type Plan
- type Profile
- type ProjectResolver
- type Proxy
- type ProxyManager
- type RejectRule
- type Sandbox
- type SandboxConfig
- type SecretResolver
- type Spec
- type StreamChunk
- type Symlink
- type TokenContext
Constants ¶
const ( StreamTypeStdout = "stdout" StreamTypeStderr = "stderr" StreamTypeExit = "exit" StreamTypeKill = "kill" )
StreamChunk is one unit in the streaming host-command protocol (Streaming=true).
Broker → Shim: type "stdout"/"stderr" carry Data; type "exit" carries ExitCode. Shim → Broker: type "kill" requests SIGTERM on the host process group.
const HostCommandRulesEnv = "BOID_HOST_COMMAND_RULES"
HostCommandRulesEnv is the name of the env var the dispatcher injects with a compact JSON map of command name -> reject rules (see internal/dispatcher/sandbox_builder.go). The shim reads it to reject obviously-doomed invocations before paying for a broker round trip. The broker remains the authority: this is a UX fast path only, and any parse failure or non-match here simply falls through to the broker check.
Variables ¶
This section is empty.
Functions ¶
func CheckPolicy ¶
func CheckPolicy(def CommandDef, args []string) bool
func CommandFromArgv0 ¶
func EarlyReject ¶ added in v0.0.9
EarlyReject checks command/args against the reject rules encoded in raw (the BOID_HOST_COMMAND_RULES JSON payload) and returns the same rejection message the broker would produce, plus true, on the first matching rule. Malformed JSON, an absent command entry, or no matching rule all yield ("", false) so callers fall through to the broker's own check.
func EarlyRejectFromEnv ¶ added in v0.0.9
EarlyRejectFromEnv is the thin env-reading wrapper around EarlyReject used by shimMain.
func RunGitShim ¶
RunGitShim forwards the raw `git` argv to the broker over the shared broker transport (sendExecRequest). Classification (direct vs. brokered), argv parsing, and policy checks all happen host-side in git_builtin.go — the shim itself does no interpretation of args.
func ShellQuote ¶
ShellQuote is the exported version of shellQuote for use outside the package.
Types ¶
type BindMount ¶
type BindMount struct {
Source string
Target string // if empty, defaults to Source
Mode string // "rw" | "" (ro default)
IsFile bool // if true, treat target as a file (touch before bind, skip type detection)
Optional bool // if true, skip mount when Source does not exist on the host
}
BindMount is the dispatcher-facing DTO for arbitrary bind-mount requests. It is used by the dispatcher boundary (via SandboxSpec.AdditionalBindings) and is converted into Mount entries at the edge. The sandbox layer itself works in terms of Mount only.
type BoidExecutor ¶
type BoidExecutor interface {
ExecuteBoidBuiltin(ctx context.Context, tokenCtx TokenContext, req *BoidRequest) *ExecResponse
}
BoidExecutor performs typed boid builtin operations after broker validation.
ctx is the broker-side request context. For most ops it carries no deadline, but for the blocking BoidOpTaskAsk it is cancelled when the broker shuts down or the sandbox connection closes, so the server-side handler can stop waiting for an answer and clean up.
type BoidOp ¶
type BoidOp string
const ( BoidOpJobDone BoidOp = "job_done" BoidOpJobList BoidOp = "job_list" BoidOpJobShow BoidOp = "job_show" BoidOpJobLog BoidOp = "job_log" BoidOpActionSend BoidOp = "action_send" BoidOpAgentStop BoidOp = "agent_stop" BoidOpTaskCreate BoidOp = "task_create" BoidOpTaskGet BoidOp = "task_get" BoidOpTaskUpdate BoidOp = "task_update" BoidOpTaskImport BoidOp = "task_import" BoidOpTaskReopen BoidOp = "task.reopen" BoidOpTaskList BoidOp = "task_list" BoidOpTaskNotify BoidOp = "task_notify" BoidOpTaskAnswer BoidOp = "task_answer" BoidOpTaskAsk BoidOp = "task_ask" BoidOpTaskDelete BoidOp = "task_delete" )
type BoidRequest ¶
type BoidRequest struct {
Op BoidOp `json:"op"`
JobID string `json:"job_id,omitempty"`
TaskID string `json:"task_id,omitempty"`
TaskField string `json:"task_field,omitempty"`
// ProjectID is extracted by the shim for broker authorization / project
// resolver; it is also present inside CreatePatch when the YAML includes
// project_id. The executor prefers createReq.ProjectID from CreatePatch
// and falls back to this field, then to ctx.ProjectID.
ProjectID string `json:"project_id,omitempty"`
ExitCode int `json:"exit_code,omitempty"`
Output string `json:"output,omitempty"`
// CreatePatch is a JSON-serialised api.CreateTaskRequest. The shim builds
// it from the full YAML map so that every field (including previously
// dropped ones such as instructions, traits, readonly, worktree,
// branch_prefix, id) is forwarded without enumeration.
CreatePatch json.RawMessage `json:"create_patch,omitempty"`
// UpdatePatch is a JSON-serialised api.UpdateTaskRequest. The shim
// assembles it from --patch-file and/or individual flags (--title,
// --description, --payload-file).
UpdatePatch json.RawMessage `json:"update_patch,omitempty"`
// task import fields
ImportTasks []json.RawMessage `json:"import_tasks,omitempty"`
ImportProjectOverride string `json:"import_project_override,omitempty"`
// task list fields
WorkspaceID string `json:"workspace_id,omitempty"`
Status string `json:"status,omitempty"`
Limit int `json:"limit,omitempty"`
// task notify fields
Message string `json:"message,omitempty"`
Ask string `json:"ask,omitempty"`
QuestionID string `json:"question_id,omitempty"`
Progress string `json:"progress,omitempty"`
Done string `json:"done,omitempty"`
Fail string `json:"fail,omitempty"`
// task answer fields
Answer string `json:"answer,omitempty"`
// task ask fields. Question carries the blocking-RPC question text for
// `boid task ask <text>`. The broker holds the connection open until the
// answer arrives; the answer is returned verbatim in ExecResponse.Stdout
// (the boid builtin reply framing is ExecResponse, so no separate
// BoidResponse type is needed).
Question string `json:"question,omitempty"`
// task delete fields
Force bool `json:"force,omitempty"`
// action send fields
ActionType string `json:"action_type,omitempty"`
Payload []byte `json:"payload,omitempty"`
}
type Broker ¶
type Broker struct {
SocketPath string
BoidBinary string
BoidExecutor BoidExecutor
ProjectResolver ProjectResolver
// contains filtered or unexported fields
}
func (*Broker) GetContext ¶
func (b *Broker) GetContext(token string) (TokenContext, bool)
func (*Broker) Handle ¶
func (b *Broker) Handle(req *ExecRequest) *ExecResponse
Handle dispatches a request using the broker's base context. Retained for callers (mainly tests) that drive the broker synchronously without a per-connection context; the live socket path uses handle with a request ctx.
func (*Broker) Register ¶
func (b *Broker) Register(commands map[string]CommandDef, builtinPolicies map[string]BuiltinPolicy, ctx TokenContext) string
func (*Broker) RegisterWithSecrets ¶
func (b *Broker) RegisterWithSecrets(commands map[string]CommandDef, builtinPolicies map[string]BuiltinPolicy, ctx TokenContext, resolver SecretResolver) string
func (*Broker) Unregister ¶
type BuiltinPolicy ¶
type BuiltinPolicy struct {
AllowedOps map[string]struct{}
// AllowedCwdRoots lists additional cwd roots permitted for this builtin
// beyond the per-token entry root (project/worktree dir). Used so that
// e.g. gate jobs can target /tmp or the host project dir without the
// broker needing to know the role itself.
AllowedCwdRoots []string
}
BuiltinPolicy defines which operations are permitted for a named builtin command. It is stamped at token registration time by the planner and checked at dispatch time by the broker, keeping all role-based authorization logic outside the broker itself.
func (BuiltinPolicy) Allows ¶
func (p BuiltinPolicy) Allows(op string) bool
Allows reports whether op is in the allowed set.
func (BuiltinPolicy) AllowsCwd ¶
func (p BuiltinPolicy) AllowsCwd(cwd string) bool
AllowsCwd reports whether cwd is within any of the policy's additional cwd roots.
type CommandDef ¶
type CommandDef struct {
Name string
Path string
AllowedPatterns []string
DeniedPatterns []string
AllowedSubcommands []string
Env map[string]string
RejectRules []RejectRule
// MissingSecrets lists "ENV_NAME (secret:key)" entries for env vars that
// the kit declared via the "secret:" prefix but failed to resolve at
// register time. When non-empty, the broker rejects exec requests for
// this command (fail-closed) instead of silently letting host env /
// host-side config fallbacks take over.
MissingSecrets []string
}
CommandDef is the canonical sandbox-side policy for brokered host commands. Dispatcher and orchestrator mirror this shape as transport data, but the policy semantics live here.
func (CommandDef) MissingSecretsMessage ¶ added in v0.0.6
func (d CommandDef) MissingSecretsMessage() string
MissingSecretsMessage returns the human-readable rejection message used when a host_command is invoked despite unresolved declared secrets. Returns an empty string if MissingSecrets is empty.
type ExecRequest ¶
type ExecRequest struct {
Command string `json:"command"`
Args []string `json:"args"`
Cwd string `json:"cwd,omitempty"`
Token string `json:"token"`
Boid *BoidRequest `json:"boid,omitempty"`
Fetch *FetchRequest `json:"fetch,omitempty"`
Streaming bool `json:"streaming,omitempty"`
}
ExecRequest carries a broker-mediated host command invocation. The broker never wires caller-provided stdin into the host process (see the host command gate in broker.go / broker_streaming_linux.go); host commands always run with stdin connected to /dev/null.
type ExecResponse ¶
type ExecResponse struct {
ExitCode int `json:"exit_code"`
Stdout string `json:"stdout"`
Stderr string `json:"stderr"`
}
func ExecFetch ¶ added in v0.0.5
func ExecFetch(req *FetchRequest) *ExecResponse
ExecFetch performs an HTTP GET on the host (no broker involved) and returns the result as an ExecResponse. Used by the `boid fetch` CLI subcommand.
func RunBoidShim ¶
func RunBoidShim(args []string) (*ExecResponse, error)
type FetchRequest ¶ added in v0.0.5
type FetchRequest struct {
URL string `json:"url"`
}
FetchRequest carries the parameters for a broker-mediated HTTP GET. Only GET is supported; the broker performs the request on the host and returns the response body (HTML converted to markdown, other types verbatim).
type FileWrite ¶
FileWrite describes a file to materialize inside the sandbox. Content is written verbatim (shell-quoted at render time); the parent directory is created with mkdir -p beforehand.
type GitBinding ¶
type GitRequest ¶
type GitRequest struct {
Op GitOp `json:"op"`
Remote string `json:"remote,omitempty"`
Refspecs []string `json:"refspecs,omitempty"`
DryRun bool `json:"dry_run,omitempty"`
Verbose bool `json:"verbose,omitempty"`
Quiet bool `json:"quiet,omitempty"`
Prune bool `json:"prune,omitempty"`
Tags bool `json:"tags,omitempty"`
Force bool `json:"force,omitempty"`
Porcelain bool `json:"porcelain,omitempty"`
ForceWithLease bool `json:"force_with_lease,omitempty"`
Delete bool `json:"delete,omitempty"`
SetUpstream bool `json:"set_upstream,omitempty"`
// Source and Dest are used exclusively for GitOpCloneLocal.
// Source is the peer project path to clone from; Dest is the destination
// directory within the current worktree. Both are validated by the broker.
Source string `json:"source,omitempty"`
Dest string `json:"dest,omitempty"`
}
type GitUpstream ¶
type HarnessType ¶ added in v0.0.6
type HarnessType string
HarnessType identifies which HarnessAdapter the runner should hand the process off to via adapter.Run(). Phase 3-d (PR1) made this field invariant non-empty for every dispatched job — hook / session / exec all resolve to shell / claude / codex / opencode. The empty string is no longer a valid value and the runner-inner-child rejects it; the legacy runExecArgv fallback was retired in the same change.
const ( // HarnessShell routes through internal/adapters/shell.Adapter.Run() and // is the fall-through for hooks without an `agent:` declaration, every // `boid exec` job, and the default for unknown agent values. Shell // adapter forwards SIGUSR1 / SIGWINCH and normalises stop-signal exits // like the agent adapters do but performs no session resolution. HarnessShell HarnessType = "shell" // HarnessClaude routes through internal/adapters/claude.Adapter.Run(). HarnessClaude HarnessType = "claude" // HarnessCodex routes through internal/adapters/codex.Adapter.Run(). // Added in Phase 3-c as a prototype to validate the HarnessAdapter // abstraction beyond claude. Minimum implementation: 1-turn launch with // signal forwarding; session resume / payload patch are deliberately // left as no-ops (see docs/plans/agent-aware-boid.md Phase 3-c). HarnessCodex HarnessType = "codex" // HarnessOpenCode routes through internal/adapters/opencode.Adapter.Run(). // Phase 3-c prototype, same scope as HarnessCodex. HarnessOpenCode HarnessType = "opencode" )
type Mount ¶
type Mount struct {
Source string // host path (empty for tmpfs)
Target string // absolute path inside sandbox
Type MountType
ReadOnly bool
Slave bool // mount --make-rslave after mounting
IsFile bool // target is a file, not a directory
DetectType bool // detect file vs dir at runtime (if/elif)
Guard string // shell test expression; if non-empty, wrap in if [ $Guard ]; then
NeedsDirs []string // subdirs to create under Target before ro remount
}
Mount describes a single filesystem mount applied inside the sandbox. Types: bind, rbind, tmpfs. Flags cover read-only remount, file vs dir handling, slave propagation, guards, and required sub-directory creation.
type NFTRule ¶ added in v0.0.6
type NFTRule struct {
Args []string
}
NFTRule is a single nftables command expressed as an argv. The go-native sandbox runner applies it with exec.Command("nft", Args...). Replaces the former []string of pre-rendered shell lines so the runner can exec nft directly without a shell.
type Plan ¶ added in v0.0.6
type Plan struct {
Mounts []Mount
Files []FileWrite
Symlinks []Symlink
NFTRules []NFTRule
CleanupPaths []string
}
Plan is the declarative description of the sandbox layout that the go-native runner materializes via syscalls. It starts with base mounts (system dirs, /dev, /proc, /tmp, DNS) plus optional nft rules and then appends everything the caller supplied in Spec.
type Profile ¶ added in v0.0.8
type Profile int
Profile selects the sandbox filesystem layout strategy. The zero value (ProfileDefault) preserves the existing behaviour so callers that do not set the field are unaffected.
const ( // ProfileDefault is the standard layout: a small set of host system dirs // (/bin, /sbin, /lib, /lib64, /usr, /etc) are ro-rbind-mounted plus // /dev, /proc, and a /tmp tmpfs. Broker socket and registration proceed // normally. This is the zero value; any Spec where Profile is not set // explicitly uses this layout. ProfileDefault Profile = iota // ProfileInit is the host-scan layout used by kit-init / workspace-configure // generation scripts. The entire host root (/) is ro-rbind-mounted so the // agent can discover installed tools without needing explicit allowlists. // Broker registration and the broker socket mount are both skipped because // init scripts do not call back into boid host-commands. ProfileInit )
type ProjectResolver ¶
ProjectResolver maps a project reference (UUID, exact name, or partial name) to a concrete project UUID. The broker calls it just before the UUID-based AllowsProject authorization check so that sandbox-side callers (e.g. plan agents) can use project names while the broker continues to enforce workspace isolation in UUID space. When nil, the broker passes refs through verbatim (tests and UUID-only callers).
type Proxy ¶
type Proxy struct {
// contains filtered or unexported fields
}
func (*Proxy) SetAllowed ¶ added in v0.0.8
SetAllowed replaces the proxy egress allowlist atomically. Subsequent CONNECT and HTTP-forward requests use the new list. Existing CONNECT tunnels (hijacked TCP connections) are unaffected — that is intentional: once an egress decision has been made for a long-lived TLS connection, pulling its destination out of the allowlist mid-stream would surface as an opaque socket close to the sandbox. Sandboxes that reconnect after SetAllowed will be re-validated against the new list.
type ProxyManager ¶ added in v0.0.8
type ProxyManager struct {
// contains filtered or unexported fields
}
ProxyManager owns a set of long-lived per-workspace HTTP(S) egress proxies. Each workspace gets its own listener on a distinct loopback port; the allowlist of every listener can be live-swapped via Proxy.SetAllowed so dispatch-time changes (workspace.yaml edits, new kit, …) take effect immediately for the next sandbox without restarting the listener.
Concurrent sandboxes launched under the same workspace share one listener — when their resolved allowlists differ, the most recent dispatch wins. This matches the semantics of the rest of the workspace surface (env, kits, …) where workspace state is read fresh at dispatch time and not frozen per-sandbox.
A ProxyManager is created via NewProxyManager and must be started with Start(ctx) before GetOrCreate is called. StopAll closes every listener; the manager is single-shot and must not be reused after StopAll.
Design rationale: per-workspace port separation (rather than embedded HTTPS_PROXY basic-auth) was chosen for client compatibility — many tools in the wild parse the proxy URL loosely or ignore the userinfo entirely.
func NewProxyManager ¶ added in v0.0.8
func NewProxyManager() *ProxyManager
NewProxyManager returns a fresh, unstarted ProxyManager.
func (*ProxyManager) Count ¶ added in v0.0.8
func (m *ProxyManager) Count() int
Count returns the number of active per-workspace listeners. Useful for diagnostics and tests; not part of the dispatch hot path.
func (*ProxyManager) GetOrCreate ¶ added in v0.0.8
func (m *ProxyManager) GetOrCreate(workspaceID string, allowed []string) (int, error)
GetOrCreate returns the port of the listener bound to workspaceID after (re)applying allowed as its egress allowlist. If no listener exists yet for workspaceID, a new one is started on a free loopback port.
allowed is copied internally — callers may mutate the slice after the call. An empty workspaceID is a programmer error: the manager refuses to allocate an unkeyed listener.
func (*ProxyManager) Start ¶ added in v0.0.8
func (m *ProxyManager) Start(ctx context.Context)
Start binds the manager to ctx. Listener teardown follows ctx cancellation; StopAll() is the explicit alternative.
func (*ProxyManager) StopAll ¶ added in v0.0.8
func (m *ProxyManager) StopAll()
StopAll closes every listener owned by the manager. Subsequent GetOrCreate calls return an error.
type RejectRule ¶ added in v0.0.9
RejectRule declares a pattern that rejects an invocation with a human-readable reason. Match is a glob over the joined args string with the same semantics as allow/deny patterns (globMatch below). Enforced by gateHostCommand (broker.go) as the authority, and mirrored by the shim's EarlyReject fast path (shim_reject.go), which needs the json tags.
type Sandbox ¶
type Sandbox interface {
Setup(cfg SandboxConfig) error
Shell(windowName string, cmd string) (string, error)
Cleanup() error
}
Sandbox provides an isolated execution environment.
type SandboxConfig ¶
type SandboxConfig struct {
ProjectDir string
WorkspaceDirs map[string]string // project-id -> dir (readonly mounts)
TaskFile string
HostCommands []string
Bindings []string
Env map[string]string
BoidBinary string
BrokerSocket string
ServerSocket string
}
SandboxConfig holds configuration for sandbox setup.
type SecretResolver ¶
type Spec ¶
type Spec struct {
// ID is the job id; it namespaces the generated /tmp/boid-<ID>-* files.
ID string
// --- Filesystem primitives ---
// Mounts are applied in order to compose the sandbox root filesystem.
Mounts []Mount
// Files are materialized inside the sandbox (after pivot_root) before the
// entry command runs.
Files []FileWrite
// Symlinks are created inside the sandbox.
Symlinks []Symlink
// --- Network ---
// ProxyPort, when > 0, engages the nft drop policy + HTTP proxy env vars.
ProxyPort int
// --- Process ---
// Argv is the program and arguments to invoke (POSIX argv).
Argv []string
// WorkDir is the cwd for the entry process. Also used as the cwd reported to
// the broker for the job-done call (must be within the project/worktree root).
WorkDir string
// Env is the environment for the entry process.
Env map[string]string
// StdinBytes, when non-empty, is piped into the entry's stdin.
StdinBytes []byte
// StdoutCaptureFile, when non-empty, redirects stdout to that sandbox-internal
// path. Doubles as the job-done output fallback when no payload patch exists.
StdoutCaptureFile string
// TTY, when true, the entry process inherits the caller's PTY on stdio.
TTY bool
// --- Completion / broker ---
// Foreground indicates a user-facing job (boid exec): stdout/stderr are
// inherited and no broker job-done callback fires on exit. Hook jobs leave
// this false so the runner posts `boid job done` through the broker.
Foreground bool
// PayloadPatchPath is the sandbox-internal path the agent writes its result
// patch to (HOME/.boid/output/payload_patch.json). The runner reads it as the
// job-done output. Broker socket path and token are carried in Env
// (BOID_BROKER_SOCKET / BOID_BROKER_TOKEN).
PayloadPatchPath string
// --- Bookkeeping ---
// RootDir, if non-empty, is the host directory used as the sandbox ROOT (a
// tmpfs is mounted on it). Go-side cleanup removes it after exit.
RootDir string
// CleanupPaths are removed by runner-outer after the sandbox process tree
// exits (used for staging dirs). Removal runs in the host mount namespace,
// where the sandbox's bind mounts are already gone.
CleanupPaths []string
// HarnessType, when non-empty, directs runner-inner-child to hand the
// agent process off to the matching HarnessAdapter.Run() instead of
// exec-ing Argv verbatim. Empty preserves the legacy exec path used by
// boid exec jobs and any non-agent hook job. See sandbox.HarnessType.
HarnessType HarnessType
// UserAnswer carries the Q&A reply that should be threaded into the
// adapter's RunContext.UserAnswer. Empty for fresh starts and for resumes
// without a Q&A reply.
UserAnswer string
// Profile selects the filesystem layout strategy. Zero value (ProfileDefault)
// preserves the existing behaviour. Set to ProfileInit for kit-init /
// workspace-configure generation scripts that need to read the full host FS.
Profile Profile
}
Spec describes a sandbox invocation in primitives only. The sandbox layer knows nothing about Role / Task / Job / Broker / Hook — all of those are the caller's concern. Everything needed to build and run the sandbox must already be present as mounts, files, env, argv, etc.
Spec is JSON-serialized by the dispatcher to /tmp/boid-<ID>-runner-spec.json and read back by the go-native runner subcommands (runner-outer / runner-inner / runner-inner-child). All fields are exported so the default encoding/json round-trip is exact.
type StreamChunk ¶
type Symlink ¶
type Symlink struct {
LinkPath string // absolute path inside sandbox (where the symlink is created)
LinkTarget string // what the symlink points to (resolved relative to LinkPath)
}
Symlink describes a symlink to create inside the sandbox.
type TokenContext ¶
type TokenContext struct {
JobID string
TaskID string
ProjectID string
WorkspaceID string
AllowedProjectIDs []string
Role string
// ProjectDir is the project's host-side work directory. Independent of
// spec.Visibility.ProjectDir (which drives sandbox mount layout and is
// intentionally empty for gate jobs): host-side operations the broker
// performs on behalf of the sandbox (git binding, host-command cwd) have
// their own notion of "which project are we operating on" that doesn't
// care whether the sandbox itself can see the tree.
ProjectDir string
WorktreeDir string
// WorkspacePeers maps peer project IDs to their host-side work directories.
// Used by the broker to validate git clone --local source paths: only paths
// within a known peer project are permitted as clone sources.
WorkspacePeers map[string]string
}
func (TokenContext) AllowsProject ¶
func (c TokenContext) AllowsProject(projectID string) bool
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
Package brokerclient holds the low-level transport for talking to the boid broker over its UNIX socket, plus a self-contained JobDone helper.
|
Package brokerclient holds the low-level transport for talking to the boid broker over its UNIX socket, plus a self-contained JobDone helper. |
|
Package runner is the go-native sandbox runner.
|
Package runner is the go-native sandbox runner. |