client

package
v0.4.2 Latest Latest
Warning

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

Go to latest
Published: Jul 21, 2026 License: Apache-2.0 Imports: 11 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 zero non-stdlib dependencies 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, GetRun, ListRuns, ListGrants, KillRun, SynthesizeProfile
  • approvals: ListApprovals, Approve, Deny
  • policies: CreatePolicy, GetPolicy, ListPolicies, UpdatePolicy, DeletePolicy
  • workspaces: CreateWorkspace, GetWorkspace, ListWorkspaces, UpdateWorkspace, DeleteWorkspace, ScanWorkspace, VerifyWorkspace, RecordWorkspaceTask
  • audit: AuditEvents, RecentAuditEvents
  • secrets: ListSecrets, SetSecret, DeleteSecret
  • site-config: GetSiteConfig, PutSiteConfig
  • setup: SetupStatus
  • identity: Me
  • health: Healthz

NOT covered (drive these with the CLI or raw HTTP): the AI Run Composer (/runs/compose*), preflight, attach WebSocket / attach-ticket, harness-login device flow, and the agent-facing /internal/* mint & decision endpoints. 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.

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 (
	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 (
	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
	GrantCloudSTS    = types.GrantCloudSTS
	GrantAPIKey      = types.GrantAPIKey
)

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.

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 ApprovalState

type ApprovalState = types.ApprovalState

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

type AuditEvent

type AuditEvent = types.AuditEvent

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

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.
	// This overrides the server-side principal attribution for multi-user dev;
	// in production the token's subject is used instead.
	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) (types.ApprovalRequest, error)

Approve transitions an approval request to APPROVED. reason is optional; pass an empty string to omit it. 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. 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.

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) (types.AgentRun, error)

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

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) 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) (types.ApprovalRequest, error)

Deny transitions an approval request to DENIED (fail closed). reason is optional; pass an empty string to omit it. 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) 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) 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: sandbox teardown, identity revocation, credential revocation, then state transition to KILLED. 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) 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) PutSiteConfig added in v0.3.1

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

PutSiteConfig replaces the operator-wide site config and returns the persisted value. PUT /api/v1/site-config.

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) 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.

func (*Client) VerifyWorkspace added in v0.3.1

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

VerifyWorkspace launches the import verify run for a workspace. Returns the raw accepted-run reply. POST /api/v1/workspaces/{id}/verify; 503 when no runner is wired; 409 while another import step is live.

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     string     `json:"task,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 (no
	// agent task is exec'd) so a human can attach to it (wardyn attach <id>).
	// Pair with a never-reap policy (AutoStopAfterSec < 0) or the idle reaper
	// will stop the idle sandbox. Task is ignored for an interactive run.
	Interactive bool `json:"interactive,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"`
	// ComposeSessionID correlates a run launched from the AI Run Composer back
	// to the compose conversation that produced it. It is stamped into the
	// run.create audit event, so filtering the audit feed on it reconstructs the
	// whole compose→launch trail. Purely a correlation label: it grants nothing
	// and is not validated server-side.
	ComposeSessionID string `json:"compose_session_id,omitempty"`
}

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

type CredentialGrant

type CredentialGrant = types.CredentialGrant

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

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 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 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"`
	Kind          types.WorkspaceKind `json:"kind"`
	Source        string              `json:"source"`
	Ref           string              `json:"ref,omitempty"`
	DefaultTarget string              `json:"default_target,omitempty"`
	// Writable opts the workspace into a READ-WRITE mount for import Record/Verify
	// runs; omitted/false is read-only (the safe default).
	Writable bool `json:"writable,omitempty"`
}

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

Jump to

Keyboard shortcuts

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