client

package
v0.5.0 Latest Latest
Warning

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

Go to latest
Published: Aug 18, 2026 License: Apache-2.0 Imports: 13 Imported by: 0

Documentation

Overview

Package client is the public Go SDK for the Wardyn control plane. It uses internal/types as the shared JSON source of truth and adds exactly one non-stdlib dependency (github.com/google/uuid, for typed ids) so it can be embedded in external tooling without friction. The in-repo `wardyn` CLI uses THIS client directly (there is no second transport); it maps APIError to process exit codes and prints APIError.Error(), which unwraps the server's {"error":...} envelope into a human-readable message.

Coverage

The SDK covers these wardynd public route families (the ones external tooling automates); it is a curated subset, NOT a 1:1 mirror of every route:

  • runs: CreateRun, Preflight, GetRun, ListRuns, ListGrants, KillRun, SynthesizeProfile, GetRecording
  • approvals: ListApprovals, Approve, Deny
  • policies: CreatePolicy, GetPolicy, ListPolicies, UpdatePolicy, DeletePolicy
  • workspaces: CreateWorkspace, GetWorkspace, ListWorkspaces, UpdateWorkspace, DeleteWorkspace, ScanWorkspace, RecordWorkspaceTask
  • sources: ListSources, CreateSource, GetSource, ScanSource, DeleteSource
  • audit: AuditEvents, AuditEventsPage, RecentAuditEvents
  • secrets: ListSecrets, SetSecret, DeleteSecret
  • site-config: GetSiteConfig, PutSiteConfig
  • setup: SetupStatus, ConnectManagedSubscription, DisconnectManagedSubscription
  • identity: Me
  • health: Healthz

NOT covered (drive these with the CLI or raw HTTP): attach WebSocket / attach-ticket, harness-login device flow, and the agent-facing /internal/* mint & decision endpoints. (The AI Run Composer's /runs/compose* used to be listed here; those routes were removed in 0.5, not left unwrapped.) TestClientCoversRouteFamilies pins that every family listed above has a method.

Pagination

The list endpoints and the audit trail accept an optional ListOpts (variadic, so existing zero-arg calls are unchanged) that sends ?limit=&offset=. A page may be truncated (the server sets X-Wardyn-Truncated); re-request with Offset advanced by len(page) to page forward. AuditEventsPage returns that signal directly as a bool instead of leaving a caller to infer completeness from len(page) == the limit it happened to pass — a guess that silently breaks the moment a caller omits Limit and gets the server's own default page size.

Usage:

c := client.New("https://wardyn.example.com", "admin-token")
run, err := c.CreateRun(ctx, client.CreateRunRequest{
    Agent: "claude-code",
    Repo:  "org/repo",
    Task:  "fix issue #42",
})

Index

Constants

View Source
const (
	SourceLocalDir = types.SourceLocalDir
	SourceRepo     = types.SourceRepo
)

SourceKind values (the tier-1 library's two onboardable kinds).

View Source
const (
	ApprovalPending  = types.ApprovalPending
	ApprovalApproved = types.ApprovalApproved
	ApprovalDenied   = types.ApprovalDenied
	ApprovalExpired  = types.ApprovalExpired
)

ApprovalState values. ListApprovals accepts one of these (or "" for all states).

View Source
const (
	ScopeOnce   = types.ScopeOnce
	ScopeRun    = types.ScopeRun
	ScopeUntil  = types.ScopeUntil
	ScopeAlways = types.ScopeAlways
)

ApprovalScope values, for DecisionOpts.Scope on Approve/Deny. Omitting Scope (or passing "") is ScopeRun — today's default, unchanged.

View Source
const (
	RunPending   = types.RunPending
	RunStarting  = types.RunStarting
	RunRunning   = types.RunRunning
	RunWaiting   = types.RunWaiting
	RunStopped   = types.RunStopped
	RunArchived  = types.RunArchived
	RunFailed    = types.RunFailed
	RunKilled    = types.RunKilled
	RunCompleted = types.RunCompleted
)

RunState values.

View Source
const (
	CC1 = types.CC1
	CC2 = types.CC2
	CC3 = types.CC3
)

ConfinementClass values.

View Source
const (
	GrantGitHubToken = types.GrantGitHubToken
	GrantGitPAT      = types.GrantGitPAT
	GrantCloudSTS    = types.GrantCloudSTS
	GrantAPIKey      = types.GrantAPIKey
	GrantSSHKey      = types.GrantSSHKey
)

GrantKind values.

View Source
const (
	ApprovalCredential   = types.ApprovalCredential
	ApprovalEgressDomain = types.ApprovalEgressDomain
	ApprovalToolCall     = types.ApprovalToolCall
)

ApprovalKind values.

View Source
const (
	ActorHuman  = types.ActorHuman
	ActorAgent  = types.ActorAgent
	ActorSystem = types.ActorSystem
)

ActorType values.

View Source
const (
	WorkspaceKindLocalDir  = types.WorkspaceKindLocalDir
	WorkspaceKindRepo      = types.WorkspaceKindRepo
	WorkspaceKindContainer = types.WorkspaceKindContainer
)

WorkspaceKind values (WorkspaceRequest.Kind). Deprecated: the legacy single-source shape; a new caller should build WorkspaceSource entries with a WorkspaceSourceType value instead.

View Source
const (
	WorkspaceSourceTypeLocalDir  = types.WorkspaceSourceTypeLocalDir
	WorkspaceSourceTypeRepo      = types.WorkspaceSourceTypeRepo
	WorkspaceSourceTypeEphemeral = types.WorkspaceSourceTypeEphemeral
)

WorkspaceSourceType values (WorkspaceSource.Type).

View Source
const (
	WorkspacePendingScan = types.WorkspacePendingScan
	WorkspaceScanning    = types.WorkspaceScanning
	WorkspaceScanned     = types.WorkspaceScanned
	WorkspaceError       = types.WorkspaceError
)

WorkspaceStatus values (Workspace.Status, Source.Status).

Variables

This section is empty.

Functions

This section is empty.

Types

type APIError

type APIError struct {
	// Status is the HTTP status code, e.g. 404.
	Status int
	// Body is the raw server response body (capped at 2048 bytes).
	Body string
}

APIError is returned when the server responds with a non-2xx status code. Status is the HTTP status code; Body is the raw response body (trimmed to 2 KiB) for diagnostic display. Callers may use errors.As to extract it.

func (*APIError) Error

func (e *APIError) Error() string

type ActorType

type ActorType = types.ActorType

ActorType distinguishes who performed an audited action (AuditEvent.ActorType).

type AgentRun

type AgentRun = types.AgentRun

AgentRun is one governed execution of a coding agent. Returned by CreateRun, GetRun, and ListRuns.

type ApprovalKind

type ApprovalKind = types.ApprovalKind

ApprovalKind enumerates what a human is being asked to approve (ApprovalRequest.Kind).

type ApprovalRequest

type ApprovalRequest = types.ApprovalRequest

ApprovalRequest is a human-in-the-loop approval gate. Returned by ListApprovals, Approve, and Deny.

type ApprovalScope added in v0.5.0

type ApprovalScope = types.ApprovalScope

ApprovalScope is how far an Approve/Deny decision reaches: once, run (the default), until, or always. Set via DecisionOpts on Approve/Deny; read back on ApprovalRequest.DecisionScope. Meaningful only for an egress_domain approval — a credential mints once by construction and a tool_call is bounded by the clamp.

type ApprovalState

type ApprovalState = types.ApprovalState

ApprovalState is the approval lifecycle state; ListApprovals filters on it (ApprovalRequest.State).

type ArtifactOverride deprecated added in v0.4.4

type ArtifactOverride = types.ArtifactOverride

ArtifactOverride is one ecosystem's artifact-registry redirect, carried in the deprecated SiteConfig.ArtifactOverrides.

Deprecated: superseded by EgressRedirect. Kept aliased so a caller that still builds the legacy shape (PutSiteConfig folds it server-side for one release) can name the element type; GetSiteConfig itself now returns this field empty.

type AuditEvent

type AuditEvent = types.AuditEvent

AuditEvent is one append-only audit record. Returned by AuditEvents.

type AuditFilter added in v0.5.0

type AuditFilter struct {
	Since        string // RFC3339, e.g. time.Now().UTC().Format(time.RFC3339)
	Until        string // RFC3339
	ActionPrefix string
	ActorType    string // "human" | "agent" | "system"
	Outcome      string // "success" | "denied" | "failure"
}

AuditFilter narrows an audit query by the server's optional predicates — ?since=&until=&action_prefix=&actor_type=&outcome= (see docs/sdk.md's Raw HTTP section). The zero value applies no filter. Since/Until are RFC3339 strings; a malformed one is rejected by the server as a 400, same as the raw HTTP API — the client does not duplicate that validation.

type BaseImageEntry added in v0.5.0

type BaseImageEntry = types.BaseImageEntry

BaseImageEntry is one tier-2 base-image catalog row: a shared, reusable image an operator saved (kind registry|custom|byo).

type Client

type Client struct {
	// BaseURL is the wardynd root, e.g. "https://wardyn.example.com".
	// A trailing slash is stripped automatically.
	BaseURL string

	// Token is the admin bearer token configured in wardynd (AdminToken).
	Token string

	// HTTPClient, when non-nil, is used instead of http.DefaultClient.
	HTTPClient *http.Client

	// Principal, when non-empty, is sent as the X-Wardyn-Principal header — a
	// DEV-ONLY override for simulating different principals against a local
	// wardynd. The server honors it ONLY in local (no-auth) mode. Under
	// admin-token auth it is ignored and the action is attributed to
	// actor_type=system / principal "admin-token" (the token is an opaque shared
	// bearer, not a JWT — there is no subject to extract); under OIDC the
	// verified subject wins. Use OIDC for real per-human attribution.
	Principal string
}

Client is the Wardyn SDK client. Construct it with New or by filling the fields directly. BaseURL and Token are required; HTTPClient defaults to http.DefaultClient when nil.

All methods accept a context; the context controls cancellation and deadline for the underlying HTTP call.

func New

func New(baseURL, token string) *Client

New returns a Client configured with baseURL and token.

func (*Client) Approve

func (c *Client) Approve(ctx context.Context, id uuid.UUID, reason string, opts ...DecisionOpts) (types.ApprovalRequest, error)

Approve transitions an approval request to APPROVED. reason is optional; pass an empty string to omit it. opts is optional (pass at most one); omitting it keeps today's default — a run-scoped approval. See DecisionOpts for once/until/always. Returns 409/APIError when the approval has already been decided. Returns 404/APIError when the approval does not exist.

func (*Client) AuditEvents

func (c *Client) AuditEvents(ctx context.Context, runID uuid.UUID, opts ...ListOpts) ([]types.AuditEvent, error)

AuditEvents returns the append-only audit trail for the specified run in chronological (seq ASC) order, unfiltered. run_id is required by the server; a zero UUID is rejected with 400. Pass a ListOpts to page a long trail: a truncated page (server sets X-Wardyn-Truncated) is walked forward with Offset += len(page), which reaches the terminal run.complete event under ASC order — prefer AuditEventsPage, which returns that signal directly instead of requiring the caller to infer it.

func (*Client) AuditEventsPage added in v0.5.0

func (c *Client) AuditEventsPage(ctx context.Context, runID uuid.UUID, filter AuditFilter, opts ...ListOpts) (events []types.AuditEvent, truncated bool, err error)

AuditEventsPage is AuditEvents plus the server's X-Wardyn-Truncated signal and the optional filter predicates (AuditFilter): truncated=true means this page did NOT reach the run's newest event (including run.complete, since the per-run trail is chronological/ASC) and the caller must page forward — Offset += len(events) — to see the rest. This is the fix for the audit-gap where a >1000-event run's newest events could silently drop with no way for a caller to even detect it: AuditEvents alone (below) cannot tell "this is everything" from "this is page 1 of more".

func (*Client) ConnectManagedSubscription added in v0.4.0

func (c *Client) ConnectManagedSubscription(ctx context.Context, provider, token string) error

ConnectManagedSubscription stores a captured provider setup-token so the proxy injects it into every eligible run (never resident in the sandbox). The value is write-only. PUT /api/v1/setup/harness-credential/{provider}.

func (*Client) CreatePolicy

func (c *Client) CreatePolicy(ctx context.Context, req PolicyRequest) (types.RunPolicy, error)

CreatePolicy validates and persists a new policy. Returns the created RunPolicy (status 201) on success; 400 on an invalid name or spec.

func (*Client) CreateRun

func (c *Client) CreateRun(ctx context.Context, req CreateRunRequest) (CreateRunResult, error)

CreateRun submits a new agent run to the control plane. Returns the created run (state PENDING or RUNNING) plus any advisory warnings. Status 201 on success; 400 on validation failure; 422 on policy/confinement mismatch; 503 when the runner is unavailable.

func (*Client) CreateSource added in v0.5.0

func (c *Client) CreateSource(ctx context.Context, req SourceRequest) (types.Source, error)

CreateSource upserts a library source by canonical identity (201 new, 200 existing row). POST /api/v1/sources.

func (*Client) CreateWorkspace added in v0.3.1

func (c *Client) CreateWorkspace(ctx context.Context, req WorkspaceRequest) (types.Workspace, error)

CreateWorkspace onboards a new workspace (status pending_scan). Returns the created row (201); 400 on an invalid body/source.

func (*Client) DeletePolicy

func (c *Client) DeletePolicy(ctx context.Context, id uuid.UUID) error

DeletePolicy removes a policy by id. Returns nil on success (204); 404/APIError when the policy does not exist.

func (*Client) DeleteSecret

func (c *Client) DeleteSecret(ctx context.Context, name string) error

DeleteSecret removes a named secret. DELETE /api/v1/secrets/{name}. Returns 403 for a reserved platform-internal name.

func (*Client) DeleteSource added in v0.5.0

func (c *Client) DeleteSource(ctx context.Context, id uuid.UUID, force bool) (detachedFrom []string, err error)

DeleteSource removes a library source. In use → 409 APIError naming the attaching workspaces; force detaches them first — those workspaces just stop mounting this source, and their next runs succeed without it (there is no loud failure at run time: the mount gate has nothing to check for a source that used to be there). detachedFrom names whichever workspaces the delete actually detached (empty when the source wasn't attached to any), the only visibility into what changed. DELETE /api/v1/sources/{id}[?force=1].

func (*Client) DeleteWorkspace added in v0.3.1

func (c *Client) DeleteWorkspace(ctx context.Context, id uuid.UUID) error

DeleteWorkspace removes a workspace by id. Returns nil (204); 404 when unknown.

func (*Client) Deny

func (c *Client) Deny(ctx context.Context, id uuid.UUID, reason string, opts ...DecisionOpts) (types.ApprovalRequest, error)

Deny transitions an approval request to DENIED (fail closed). reason is optional; pass an empty string to omit it. opts is optional (pass at most one); omitting it keeps today's default — a run-scoped denial. See DecisionOpts for once/until/always. Returns 409/APIError when the approval has already been decided. Returns 404/APIError when the approval does not exist.

func (*Client) DisconnectManagedSubscription added in v0.4.0

func (c *Client) DisconnectManagedSubscription(ctx context.Context, provider string) error

DisconnectManagedSubscription removes a provider's stored managed subscription token. DELETE /api/v1/setup/harness-credential/{provider}.

func (*Client) GetPolicy

func (c *Client) GetPolicy(ctx context.Context, id uuid.UUID) (types.RunPolicy, error)

GetPolicy fetches a single RunPolicy by its UUID. Returns 404/APIError when the policy does not exist.

func (*Client) GetRecording added in v0.4.4

func (c *Client) GetRecording(ctx context.Context, runID uuid.UUID, session ...string) (io.ReadCloser, error)

GetRecording streams a run's terminal recording as raw asciicast bytes (the .cast a player consumes). The caller MUST Close the returned reader. GET /api/v1/runs/{id}/recording/{key} — the id really does appear twice: the route is mounted per-run and its handler takes the recording's own CAST KEY, which defaults to the bare run id (a batch run's single recording) when session is omitted — existing zero-arg callers are unaffected. An INTERACTIVE run can carry multiple recordings, one per attach session, each keyed "<runID>~<session>" (recording.CastKey — see internal/recording's own doc comment); pass that session id as the optional session argument to fetch one of those instead of the run's own bare-id cast. At most one value is meaningful; variadic only to keep it optional without a second method name. Returns 404/APIError when the run/session has no recording.

func (*Client) GetRun

func (c *Client) GetRun(ctx context.Context, id uuid.UUID) (types.AgentRun, error)

GetRun fetches a single AgentRun by its UUID. Returns 404/APIError when the run does not exist.

func (*Client) GetSiteConfig added in v0.3.1

func (c *Client) GetSiteConfig(ctx context.Context) (types.SiteConfig, error)

GetSiteConfig returns the operator-wide site config. GET /api/v1/site-config.

func (*Client) GetSource added in v0.5.0

func (c *Client) GetSource(ctx context.Context, id uuid.UUID) (types.Source, error)

GetSource fetches one library source. GET /api/v1/sources/{id}.

func (*Client) GetWorkspace added in v0.3.1

func (c *Client) GetWorkspace(ctx context.Context, id uuid.UUID) (types.Workspace, error)

GetWorkspace fetches a single workspace by id. Returns 404/APIError when unknown.

func (*Client) Healthz added in v0.3.1

func (c *Client) Healthz(ctx context.Context) (json.RawMessage, error)

Healthz returns the control-plane health payload as raw JSON. GET /healthz (note: NOT under /api/v1, and unauthenticated).

func (*Client) KillRun

func (c *Client) KillRun(ctx context.Context, id uuid.UUID) (KillRunResponse, error)

KillRun initiates the kill sequence for a run: durable state transition (compare-and-swap to KILLED) first, then sandbox teardown, identity revocation, and credential revocation. Returns 202/Accepted with the final state on success. Returns 404/APIError when the run does not exist.

func (*Client) ListApprovals

func (c *Client) ListApprovals(ctx context.Context, state types.ApprovalState, opts ...ListOpts) ([]types.ApprovalRequest, error)

ListApprovals returns approval requests filtered by state. Pass an empty string to return all states. Valid states: "PENDING", "APPROVED", "DENIED", "EXPIRED" (types.ApprovalState).

func (*Client) ListGrants

func (c *Client) ListGrants(ctx context.Context, runID uuid.UUID) ([]types.CredentialGrant, error)

ListGrants returns the credential-grant eligibility records for a run. These are eligibility records (what the run MAY request), not issued credentials — some may never be minted. Returns 404/APIError when the run does not exist.

func (*Client) ListPolicies

func (c *Client) ListPolicies(ctx context.Context, opts ...ListOpts) ([]types.RunPolicy, error)

ListPolicies returns run policies in reverse creation order. Pass a ListOpts to page.

func (*Client) ListRuns

func (c *Client) ListRuns(ctx context.Context, opts ...ListOpts) ([]types.AgentRun, error)

ListRuns returns runs in reverse creation order. Pass a ListOpts to page.

func (*Client) ListSecrets

func (c *Client) ListSecrets(ctx context.Context) ([]string, error)

ListSecrets returns the managed secret NAMES (never values). Reserved platform-internal keys are excluded server-side. GET /api/v1/secrets, which responds {"names":[...]}.

func (*Client) ListSources added in v0.5.0

func (c *Client) ListSources(ctx context.Context) ([]types.Source, error)

ListSources returns the whole library. GET /api/v1/sources.

func (*Client) ListWorkspaces added in v0.3.1

func (c *Client) ListWorkspaces(ctx context.Context, opts ...ListOpts) ([]types.Workspace, error)

ListWorkspaces returns onboarded workspaces in reverse creation order. Pass a ListOpts to page.

func (*Client) Me added in v0.3.1

func (c *Client) Me(ctx context.Context) (json.RawMessage, error)

Me returns the caller's resolved identity/attribution as raw JSON. GET /api/v1/me.

func (*Client) Preflight added in v0.4.4

func (c *Client) Preflight(ctx context.Context, req CreateRunRequest) (PreflightResult, error)

Preflight DRY-RUNs a create-run request: the server resolves the policy through the same chokepoint launch uses (so an XOR violation, an unknown secret, or a non-onboarded workspace surface as the REAL launch error) and returns the setup checklist plus the enforced confinement class. It mints nothing, persists nothing, dispatches nothing. Pass the exact CreateRunRequest you would launch with. POST /api/v1/runs/preflight.

func (*Client) PutSiteConfig added in v0.3.1

func (c *Client) PutSiteConfig(ctx context.Context, cfg types.SiteConfig) (out types.SiteConfig, danglingSecretRefs []string, err error)

PutSiteConfig replaces the operator-wide site config and returns the persisted value plus danglingSecretRefs — the names of any secret the document now references that the secret store doesn't currently hold (e.g. a `site-config apply` recovery run before the referenced secrets were restored). Advisory only, never an error: the ref is still saved as given. PUT /api/v1/site-config.

Integrations is stripped from cfg before the request: the server rejects a non-empty one outright (integrations are managed through their own endpoints, never PUT /site-config), so the documented disaster-recovery round-trip — `wardyn site-config get > f` before a reset, `wardyn site-config apply f` after — 400ed outright the moment any integration was ever stored (PLATFORM-API-5). Stripped here, once, so no caller has to remember to (mirrors ui/src/app/lib/api/health.ts's identical fix on the TS side).

func (*Client) RecentAuditEvents added in v0.3.1

func (c *Client) RecentAuditEvents(ctx context.Context, opts ...ListOpts) ([]types.AuditEvent, error)

RecentAuditEvents returns the newest-first global audit feed (all runs) — the SIEM-style tail the Audit view renders. Pass a ListOpts to page.

func (*Client) RecordWorkspaceTask added in v0.3.1

func (c *Client) RecordWorkspaceTask(ctx context.Context, wsID uuid.UUID, taskKey string) (RecordTaskResult, error)

RecordWorkspaceTask launches a named open (allow-all egress) recording session for a workspace via the import pipeline — the operator attaches, does the real activity, and stops the run to capture what it actually used. POST /api/v1/workspaces/{id}/record with body {"task_key": name}. Returns 202 with the launched run; 503 when no runner is wired; 409 while another import step is live.

func (*Client) ScanSource added in v0.5.0

func (c *Client) ScanSource(ctx context.Context, id uuid.UUID) (json.RawMessage, error)

ScanSource scans one source — a dir inline (200 with the profile), a repo as a governed run (202 with scan_run_id). The reply shape varies, so it is returned raw. POST /api/v1/sources/{id}/scan.

func (*Client) ScanWorkspace added in v0.3.1

func (c *Client) ScanWorkspace(ctx context.Context, id uuid.UUID) (json.RawMessage, error)

ScanWorkspace triggers the workspace scan (populates the least-privilege profile). The reply shape varies (a completed profile vs an accepted async run), so it is returned as raw JSON. POST /api/v1/workspaces/{id}/scan.

func (*Client) SetSecret

func (c *Client) SetSecret(ctx context.Context, name, value string) error

SetSecret stores (or overwrites) a named secret. The value is write-only — no API path ever returns it. PUT /api/v1/secrets/{name} with body {"value":...}. Returns 400 on an invalid name, 403 for a reserved platform-internal name.

func (*Client) SetupStatus added in v0.3.1

func (c *Client) SetupStatus(ctx context.Context) (json.RawMessage, error)

SetupStatus returns the first-run setup checklist as raw JSON (the response is a server-internal struct not exported through internal/types). GET /api/v1/setup/status.

func (*Client) SynthesizeProfile added in v0.3.1

func (c *Client) SynthesizeProfile(ctx context.Context, runID uuid.UUID) (ProfileResult, error)

SynthesizeProfile runs Recording Mode synthesis for a run: from its already- captured audit / egress / ground-truth events the server proposes a tightened, reusable RunPolicy ("sandbox profile"). ADVISORY and READ-ONLY — it mints nothing and persists no policy (save the proposal via CreatePolicy). POST /api/v1/runs/{id}/profile. Returns 404 when the run does not exist.

func (*Client) UpdatePolicy

func (c *Client) UpdatePolicy(ctx context.Context, id uuid.UUID, req PolicyRequest) (types.RunPolicy, error)

UpdatePolicy validates and replaces an existing policy's name and spec. Returns the updated RunPolicy on success; 404 when unknown; 400 when invalid.

func (*Client) UpdateWorkspace added in v0.3.1

func (c *Client) UpdateWorkspace(ctx context.Context, id uuid.UUID, req WorkspaceRequest) (types.Workspace, error)

UpdateWorkspace replaces a workspace's editable identity fields. Returns the updated row; 404 when unknown; 400 when invalid.

type ConfinementClass

type ConfinementClass = types.ConfinementClass

ConfinementClass declares how strongly a sandbox confines an agent (AgentRun.ConfinementClass, RunPolicySpec.MinConfinementClass).

type CreateRunRequest

type CreateRunRequest struct {
	Agent string `json:"agent"`
	Repo  string `json:"repo"`
	// Task is the agent's prompt for a non-interactive run. For an interactive
	// run it is instead the OPTIONAL boot seed: interpreted per
	// InteractiveStart (an initial prompt for "agent", a startup command for
	// "shell") and fired once, at sandbox boot, in the same persistent session
	// the human later attaches to — never re-run on attach. Empty is today's
	// pure-idle behavior, unchanged.
	Task string `json:"task,omitempty"`
	// Title is a short human NAME for the run. Runs that share a title are
	// grouped in the console's run list. OPTIONAL on the wire even though the
	// console requires it: the site-config probe, harness login and workspace
	// record/verify all create runs with no human to name them, and the console
	// falls back to Task for display. Trimmed and stored on the run row.
	Title string `json:"title,omitempty"`
	// Description is optional free-text context — why this run exists. Never
	// interpreted, only stored and displayed.
	Description string     `json:"description,omitempty"`
	PolicyID    *uuid.UUID `json:"policy_id,omitempty"`
	// ConfinementClass, when set, requests a specific confinement class
	// ("CC1"/"CC2"/"CC3"). Empty inherits the policy minimum; an unknown
	// non-empty value is rejected by the server with 400.
	ConfinementClass string `json:"confinement_class,omitempty"`
	// Interactive requests an interactive run: the sandbox comes up idle — or,
	// with a non-empty Task, runs that boot seed in a persistent session — so a
	// human can attach to it (wardyn attach <id>) either way. Pair with a
	// never-reap policy (AutoStopAfterSec < 0) or the idle reaper will stop the
	// idle sandbox.
	Interactive bool `json:"interactive,omitempty"`
	// WorkspaceID, when set, launches the run against that ONBOARDED workspace:
	// the server prepends the workspace's stored source onto the resolved policy
	// (a repo as a workspace_repos entry, a local dir as a read-only-by-default
	// workspace_mounts entry) so the run inherits its approved egress, built image
	// and bound model/harness credentials. Composes with PolicyID / InlinePolicy /
	// the default policy — it seeds the source those cannot name without
	// hand-reproducing the workspace's exact path. Container-kind workspaces are
	// rejected: pass the image ref as Image instead.
	WorkspaceID *uuid.UUID `json:"workspace_id,omitempty"`
	// InlinePolicy, when set, supplies the run's full RunPolicySpec INLINE
	// instead of referencing a stored PolicyID. It is MUTUALLY EXCLUSIVE with
	// PolicyID (the server rejects both with 400); neither set falls back to the
	// configured default. The server validates it exactly like a stored policy
	// (mounts pass the same deny-list; api_key grants must reference an existing
	// secret) and attaches it with no stored policy id.
	InlinePolicy *RunPolicySpec `json:"inline_policy,omitempty"`
	// DevcontainerRepo, when set AND an image builder is wired (WARDYN_ENVBUILD),
	// triggers a devcontainer build of that git repo whose resulting image becomes
	// the sandbox image. Ignored (degrades to the convention image) when no builder
	// is wired. Mutually exclusive with Image.
	DevcontainerRepo string `json:"devcontainer_repo,omitempty"`
	// DevcontainerRef is the optional git ref (branch/tag/sha) to build for
	// DevcontainerRepo.
	DevcontainerRef string `json:"devcontainer_ref,omitempty"`
	// Image, when set, is a USER-supplied base image (Bring Your Own Image); the
	// server wraps it with the runner tools via a trusted finalize stage and
	// requires an image builder to be wired (WARDYN_ENVBUILD) — an explicit
	// Image with no builder wired is a hard 400 rather than a silent fallback.
	// Mutually exclusive with DevcontainerRepo.
	Image string `json:"image,omitempty"`
	// TaskMode selects how a non-interactive run executes Task: "" / "harness"
	// (default) runs the agent harness; "exec" runs Task as a plain shell
	// command in the same governed sandbox (no agent, no LLM credentials — the
	// BYOA/CI lane; see docs/CI.md). Ignored for an interactive run.
	TaskMode string `json:"task_mode,omitempty"`
	// InteractiveStart is TaskMode's interactive counterpart: what the attach
	// shell opens with. "" / "shell" drops the human into a shell in the
	// prepared workspace (the long-standing behavior); "agent" additionally
	// launches the image's agent CLI (claude / codex) there, once, on the first
	// attach. Request-scoped like TaskMode — never persisted on the run row,
	// carried to the sandbox as WARDYN_INTERACTIVE_START and consumed by the
	// image's attach ~/.bashrc. Ignored for a non-interactive run.
	InteractiveStart string `json:"interactive_start,omitempty"`
	// SeedAutoTools, when true, lets an interactive run's boot SEED (Task,
	// interpreted per InteractiveStart — see Task's own doc) use tools before a
	// human attaches, equivalent to --dangerously-skip-permissions for that
	// pre-attach span only. Default false: the seed is supervised, so an
	// unattended agent-started seed parks at its first tool-approval prompt
	// until someone joins. Meaningful only for an agent-started seed with
	// non-empty Task; request-scoped like InteractiveStart — never persisted on
	// the run row, carried to the sandbox as WARDYN_SEED_AUTO_TOOLS.
	SeedAutoTools bool `json:"seed_auto_tools,omitempty"`
	// ToolApprovals governs an AUTONOMOUS (non-interactive) Claude Code run's
	// own tool calls: "" / "auto" (default) is today's behavior — the sandbox
	// and egress policy are the only boundary, same as
	// --dangerously-skip-permissions; "hold" routes every tool call through
	// Wardyn's approval FSM instead, so an operator decides each one before it
	// runs. Rejected for codex-cli (no external tool-approval contract) and
	// structurally inert for an interactive run (that run's own supervised-seed
	// posture is SeedAutoTools's job, not this field's). Request-scoped like
	// TaskMode — never persisted on the run row, carried to the sandbox as
	// WARDYN_TOOL_APPROVALS.
	ToolApprovals string `json:"tool_approvals,omitempty"`
	// Workspaces carries PER-WORKSPACE options — which of a workspace's
	// OPTIONAL requirements (types.Workspace.Requirements, level="optional")
	// this run enables, and a read-only narrowing — for the workspaces this run
	// attaches. Additive to WorkspaceID, which stays a working SINGLE-selection
	// alias: a caller that sets only WorkspaceID (never touching Workspaces)
	// gets exactly today's behavior — no optional requirement enabled, no
	// narrowing. A REQUIRED requirement needs no entry here at all; it applies
	// automatically whenever its workspace is used. A selection naming a
	// workspace this run does not otherwise attach (via WorkspaceID or a
	// policy's workspace_mounts/workspace_repos) does nothing.
	Workspaces []WorkspaceSelection `json:"workspaces,omitempty"`
	// IntegrationID, when set, pins this run's model/harness credential to a
	// SPECIFIC AI-provider Integration (SiteConfig.Integrations[i].ID, stored
	// or a well-known legacy-derived id — see GET /integrations), overriding
	// any workspace LLMCred binding and the operator's DefaultFor:agent_runs
	// default. Naming a non-AI-provider integration (a source-control or
	// corporate-network id — those apply operator-wide already, and are never
	// run-selectable) is a 400.
	IntegrationID string `json:"integration_id,omitempty"`
}

CreateRunRequest is the body for POST /api/v1/runs.

type CreateRunResult added in v0.4.4

type CreateRunResult struct {
	types.AgentRun
	// Warnings are ADVISORY notices the server raised while resolving the run —
	// discouraged, never blocking: a workspace-directory collision with another
	// active run, or an ssh_key grant dropped because the agent has no SSH clone
	// lane. Surface them: the run is live either way, so a dropped warning is a
	// silently degraded run.
	Warnings []string `json:"warnings,omitempty"`
}

CreateRunResult is the decoded POST /api/v1/runs 201 reply. AgentRun is EMBEDDED (the server puts the run's fields at the top level), so .ID/.State read straight off the result.

type CredentialGrant

type CredentialGrant = types.CredentialGrant

CredentialGrant is a credential-grant eligibility record. Returned by ListGrants.

type DecisionOpts added in v0.5.0

type DecisionOpts struct {
	// Scope is the decision's blast radius: ScopeOnce, ScopeRun (the zero
	// value, and today's default), ScopeUntil, or ScopeAlways. Meaningful
	// only for an egress_domain approval; the server rejects it otherwise.
	Scope ApprovalScope
	// Until is the expiry for Scope == ScopeUntil: required by the server in
	// that case, and rejected if set for any other scope.
	Until *time.Time
}

DecisionOpts is the optional scope/expiry for Approve/Deny. This repo has no WithX functional-option precedent (see ListOpts); DecisionOpts follows the same plain-struct-passed-variadically shape. Pass at most one.

type EgressRedirect added in v0.5.0

type EgressRedirect = types.EgressRedirect

EgressRedirect is one outbound redirect (package registry or otherwise), carried in SiteConfig.EgressRedirects. Aliased for the same reason as ArtifactOverride: GetSiteConfig returns a nil slice when unconfigured, so without a nameable element type a caller could not author one at all.

type GrantKind

type GrantKind = types.GrantKind

GrantKind enumerates broker-mintable credential kinds (GrantSpec.Kind).

type GrantSpec

type GrantSpec = types.GrantSpec

GrantSpec is a credential scope description carried in RunPolicySpec.EligibleGrants.

type KillRunResponse

type KillRunResponse struct {
	ID    uuid.UUID      `json:"id"`
	State types.RunState `json:"state"`
}

KillRunResponse is the body returned by POST /api/v1/runs/{id}/kill.

type ListOpts added in v0.3.1

type ListOpts struct {
	Limit  int
	Offset int
}

ListOpts carries the server's ?limit=&offset= pagination for the list and audit endpoints. The zero value sends nothing, so the server applies its default page size. Methods take it variadically; pass at most one.

type PolicyRequest

type PolicyRequest struct {
	Name string              `json:"name"`
	Spec types.RunPolicySpec `json:"spec"`
}

PolicyRequest is the body for POST/PUT /api/v1/policies. Name is required; Spec is validated server-side before persistence (a bad spec is rejected with 400, fail closed).

type PreflightItem added in v0.4.4

type PreflightItem struct {
	Kind       string `json:"kind"`
	ID         string `json:"id"`
	Label      string `json:"label"`
	RequiredBy string `json:"required_by"`
	Status     string `json:"status"` // "satisfied" | "missing" | "unverified"
	Detail     string `json:"detail,omitempty"`
}

PreflightItem is one row of the preflight setup checklist: something the run needs, and whether it is already satisfied. Only the fields callers render are modeled — the full server row additionally carries a structured UI "fix" action and a credential-residency label.

type PreflightResult added in v0.4.4

type PreflightResult struct {
	SetupItems               []PreflightItem        `json:"setup_items"`
	EnforcedConfinementClass types.ConfinementClass `json:"enforced_confinement_class"`
	// Warnings carries resolveRunPolicy's clamp notes — a member's silently
	// narrowed inline policy, a filtered grant. The dry run is the ONLY place
	// these surface (launch never returns them), so dropping them here left a
	// member with no way to learn their policy was clamped at all.
	Warnings []string `json:"warnings,omitempty"`
}

PreflightResult is the decoded POST /api/v1/runs/preflight reply: the setup checklist plus the confinement class the run would ACTUALLY enforce after the policy floor and blast-radius raise.

type ProfileResult added in v0.3.1

type ProfileResult struct {
	Proposed struct {
		InlinePolicy RunPolicySpec `json:"inline_policy"`
	} `json:"proposed"`
	OverallRisk  string `json:"overall_risk"`
	Observations struct {
		Domains []struct {
			Host    string   `json:"host"`
			Methods []string `json:"methods"`
		} `json:"domains"`
		Anomalies []string `json:"anomalies"`
	} `json:"observations"`
	Warnings []string `json:"warnings"`
}

ProfileResult is the decoded POST /api/v1/runs/{id}/profile reply (Recording Mode): the synthesized least-privilege sandbox profile plus the observations it was built from. Only the fields callers render/save are modeled — the full server response (profileResponse) additionally carries a per-item risk breakdown the SDK does not surface.

type RecordTaskResult added in v0.3.1

type RecordTaskResult struct {
	RecordRunID string   `json:"record_run_id"`
	TaskKey     string   `json:"task_key"`
	Mode        string   `json:"mode"`
	Detail      string   `json:"detail"`
	Warnings    []string `json:"warnings"`
}

RecordTaskResult is the decoded POST /api/v1/workspaces/{id}/record reply: the launched open-egress recording run plus the resolved session key/mode.

type RunPolicy

type RunPolicy = types.RunPolicy

RunPolicy is a declarative policy attached to runs. Returned by the policy methods (ListPolicies, GetPolicy, CreatePolicy, UpdatePolicy).

type RunPolicySpec

type RunPolicySpec = types.RunPolicySpec

RunPolicySpec is the policy body carried in PolicyRequest.Spec. As a true `=` alias it carries the full wire surface, including AllowAllEgress (json:"allow_all_egress,omitempty") for the "allow all (deny-list only)" egress mode — no separate SDK struct to keep in sync.

type RunState

type RunState = types.RunState

RunState is the AgentRun lifecycle state (AgentRun.State, KillRunResponse.State).

type SiteConfig added in v0.4.4

type SiteConfig = types.SiteConfig

SiteConfig is the operator-wide site config. Returned by GetSiteConfig and accepted by PutSiteConfig.

type Source added in v0.5.0

type Source = types.Source

Source is one tier-1 library entry: a repo/dir configured once (its own contract + scan) and attached to many workspaces.

type SourceKind added in v0.5.0

type SourceKind = types.SourceKind

SourceKind discriminates a library source: local_dir | repo.

type SourceRequest added in v0.5.0

type SourceRequest struct {
	Kind types.SourceKind `json:"kind"`
	// Locator is a host directory path (local_dir) or repo slug/clone URL (repo).
	Locator string `json:"locator"`
	// Ref is an optional git ref; repo only. Part of the identity — the same
	// repo at two refs is two sources with two contracts.
	Ref  string `json:"ref,omitempty"`
	Name string `json:"name,omitempty"`
	// Requirements seeds the source's own contract (secret:/egress:/write:
	// keys; integration: keys are tier-3-only and rejected here).
	Requirements map[string]types.WorkspaceRequirement `json:"requirements,omitempty"`
}

SourceRequest is the body for POST /api/v1/sources — one repo/dir configured ONCE (its own requirements contract, its own scan profile) and attached to any number of workspaces. The server dedupes on canonical identity (kind, locator, ref): re-creating an existing source answers 200 with the existing row, contract and all, rather than a duplicate.

type Workspace added in v0.4.4

type Workspace = types.Workspace

Workspace is an onboarded local dir / repo / container. Returned by ListWorkspaces, GetWorkspace, CreateWorkspace, and UpdateWorkspace.

type WorkspaceAttachment added in v0.5.0

type WorkspaceAttachment = types.WorkspaceAttachment

WorkspaceAttachment is one tier-3 composition row (Workspace.Attachments): either a library Source reference (SourceID set) or an inline ephemeral scratch row.

type WorkspaceBaseImage added in v0.5.0

type WorkspaceBaseImage = types.WorkspaceBaseImage

WorkspaceBaseImage is a Workspace's base-image choice, carried in WorkspaceRequest.BaseImage and returned in Workspace.BaseImage.

type WorkspaceBedrockRef added in v0.4.4

type WorkspaceBedrockRef = types.WorkspaceBedrockRef

WorkspaceBedrockRef is a Bedrock region/model selection. Aliased because it is a pointer-field shape a caller may need to build (dispatchParams. BedrockRef server-side); no current WorkspaceLLMCred field carries one — that binding resolves through an Integration (see WorkspaceLLMCred) — but the type is kept nameable for that resolution's future wiring.

type WorkspaceKind added in v0.4.4

type WorkspaceKind = types.WorkspaceKind

WorkspaceKind is what a workspace onboards (Workspace.Kind, WorkspaceRequest.Kind). Deprecated: a DERIVED READ-ONLY MIRROR of Workspace.Sources[0] (single-source only) — see WorkspaceSourceType for the field a multi-source Workspace actually carries per-source.

type WorkspaceLLMCred added in v0.4.4

type WorkspaceLLMCred = types.WorkspaceLLMCred

WorkspaceLLMCred is the operator-owned model/harness credential binding carried in WorkspaceRequest.LLMCred: IntegrationRef names a SiteConfig.Integrations entry this workspace's model/harness access resolves through. "" (or a nil WorkspaceLLMCred) means no binding.

type WorkspaceMount

type WorkspaceMount = types.WorkspaceMount

WorkspaceMount is an operator/policy-controlled host bind mount carried in RunPolicySpec.WorkspaceMounts.

type WorkspaceRequest added in v0.3.1

type WorkspaceRequest struct {
	Name string `json:"name"`
	// Sources is the workspace's composition: one-or-more local_dir/repo/
	// ephemeral sources. Mutually exclusive with the legacy scalar fields
	// below (Kind/Source/Ref/DefaultTarget/Writable) — set one or the other,
	// never both. Omitting both onboards the composition floor: one ephemeral
	// scratch source.
	Sources []types.WorkspaceSource `json:"sources,omitempty"`
	// BaseImage is the workspace's base-image choice. Nil means the platform
	// default convention image for the detected/scanned stack.
	BaseImage *types.WorkspaceBaseImage `json:"base_image,omitempty"`

	// Deprecated: Kind/Source/Ref/DefaultTarget/Writable are the pre-
	// composition-model scalar shape — a single source, folded server-side
	// into Sources[0] (legacyWorkspaceSource). Kept so
	// `wardyn workspace create --kind local_dir --source /x` and existing SDK
	// callers keep working; prefer Sources for a new caller, especially a
	// multi-source one.
	Kind          types.WorkspaceKind `json:"kind,omitempty"`
	Source        string              `json:"source,omitempty"`
	Ref           string              `json:"ref,omitempty"`
	DefaultTarget string              `json:"default_target,omitempty"`
	// Deprecated: see Kind. Writable opts the single legacy source into a
	// READ-WRITE mount for import Record/Verify runs; omitted/false is
	// read-only (the safe default). A sandboxed agent's changes then PERSIST
	// to the host directory. A multi-source caller sets WorkspaceSource.Writable
	// per source instead.
	Writable bool `json:"writable,omitempty"`
	// LLMCred is the operator-owned model/harness credential BINDING for this
	// workspace/container (refs/names only). A run that picks the workspace
	// inherits this model access. Nil => no binding. CREATE-ONLY: the update
	// handler ignores it, so changing a binding needs the standalone
	// PUT /workspaces/{id}/llm-cred route (not covered by this SDK).
	LLMCred *types.WorkspaceLLMCred `json:"llm_cred,omitempty"`
}

WorkspaceRequest is the body for POST/PUT /api/v1/workspaces. Name is required, plus either Sources or the legacy scalar shape (Kind+Source); the server validates each source with the same deny-list the run path uses (local_dir bind-mount safety, repo slug/URL shape) before persisting.

internal/api aliases this type (`type workspaceRequest = client.WorkspaceRequest`) so server and SDK cannot drift; the server rejects unknown JSON fields, so a field missing here is unreachable from the SDK rather than merely undocumented.

type WorkspaceRequirement added in v0.5.0

type WorkspaceRequirement = types.WorkspaceRequirement

WorkspaceRequirement is one entry in Workspace.Requirements.

type WorkspaceSelection added in v0.5.0

type WorkspaceSelection struct {
	// WorkspaceID is the workspace this selection applies to (string form of
	// its uuid — matched against the run's referenced workspaces by id).
	WorkspaceID string `json:"workspace_id"`
	// EnabledOptional lists the workspace's OPTIONAL requirement KEYS (the
	// exact "<type>:<key>" form, e.g. "egress:api.stripe.com" or
	// "write:/home/user/repo") this run opts into. A key not listed here stays
	// at its safe default (no egress, no grant, read-only mount).
	EnabledOptional []string `json:"enabled_optional,omitempty"`
	// ReadOnly, when set, NARROWS this workspace's write:<path> requirements —
	// true forces every one read-only even if Required or enabled; false is a
	// no-op (a selection may only narrow what the contract already grants,
	// never widen it — see the fold in internal/api/runs_create.go). Nil
	// leaves the contract's own resolved default in effect.
	ReadOnly *bool `json:"read_only,omitempty"`
}

WorkspaceSelection is one per-run option set for an attached workspace. See CreateRunRequest.Workspaces.

type WorkspaceSource added in v0.5.0

type WorkspaceSource = types.WorkspaceSource

WorkspaceSource is one entry in a Workspace's composition, carried in WorkspaceRequest.Sources and returned in Workspace.Sources.

type WorkspaceSourceType added in v0.5.0

type WorkspaceSourceType = types.WorkspaceSourceType

WorkspaceSourceType discriminates a WorkspaceSource's kind (local_dir | repo | ephemeral).

type WorkspaceStatus added in v0.5.0

type WorkspaceStatus = types.WorkspaceStatus

WorkspaceStatus is the onboarding/scan lifecycle of a Workspace or Source (Workspace.Status, Source.Status): not-yet-scanned, mid-scan, scanned (ready to use), or errored.

Jump to

Keyboard shortcuts

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