Documentation
¶
Overview ¶
Package gaiadesk is the official Go SDK for GaiaDesk's Platform API (https://api.gaiadesk.net/v1): your fleet of desks, their reachability, waking them, the audit trail, webhooks, support sessions, and desk operations (commands, background jobs, files, tokens, stats) relayed to your desks, end-to-end encrypted when the desk can open them.
Three transports speak the same /v1 API, with the same methods, results and errors:
- New: the hosted API, with an Atlas API key (`ak_…`) or a signed-in person's session token. Desk operations from an API key also need a scoped agent token (WithDeskToken, `gdagt_…`), which the desk verifies.
- NewLocal: code running ON a desk, through the GaiaDesk app's own API over its Unix socket (~/.gaiadesk/api.sock) or Windows named pipe (\\.\pipe\gaiadesk-api-<user>), with the desk's local admin token or an agent token.
- NewLAN: a desk's opt-in LAN gateway (https://<desk>:7443/v1), its self-signed certificate pinned by SHA-256 fingerprint; agent tokens only.
Every method takes a context.Context; cancelling it stops the call (a stream ends with exit 130). Failures are *Error values carrying the API's error envelope (Class, Reason, Desk, Status, RequestID, RetryAfter); match them with errors.Is against ErrRefused, ErrUnreachable, ErrUsage, … or read them with AsError.
End-to-end encryption: on the hosted API, a desk operation is sealed to the desk's X25519 key (X25519, HKDF-SHA256, XChaCha20-Poly1305) whenever the desk publishes one, so the API relays only ciphertext; every result, stream event and error is what the plaintext call gives. See WithE2E and WithE2EKeys.
Index ¶
- Constants
- Variables
- func LocalAPIDir(getenv func(string) string, home, goos string) string
- func LocalPipeName(getenv func(string) string, username string) string
- func LocalSocketPath(getenv func(string) string, home, goos string) string
- func LocalTokenPath(getenv func(string) string, home, goos string) string
- func NormalizeFingerprint(fp string) (string, error)
- func ParseDuration(s string) (time.Duration, error)
- func PipeUser(name string) string
- func SignWebhook(secret string, body []byte, t time.Time) string
- func VerifyWebhook(secret, signature string, body []byte, now time.Time) error
- type AuditEvent
- type AuditFilter
- type CallOption
- type Chunk
- type Class
- type CliError
- type Client
- func (c *Client) Audit(ctx context.Context, f *AuditFilter, opts ...CallOption) ([]AuditEvent, error)
- func (c *Client) AuditAll(ctx context.Context, f *AuditFilter, opts ...CallOption) iter.Seq2[AuditEvent, error]
- func (c *Client) BaseURL() string
- func (c *Client) CreateSupportSession(ctx context.Context, s SupportSessionRequest, opts ...CallOption) (*SupportSessionCreated, error)
- func (c *Client) CreateToken(ctx context.Context, t TokenRequest, opts ...CallOption) (*MintResult, error)
- func (c *Client) CreateWebhook(ctx context.Context, w WebhookRequest, opts ...CallOption) (*WebhookCreated, error)
- func (c *Client) DeleteWebhook(ctx context.Context, id string, opts ...CallOption) error
- func (c *Client) Desk(ctx context.Context, desk string, opts ...CallOption) (*DeskDetail, error)
- func (c *Client) Desks(ctx context.Context, opts ...CallOption) (*DeskList, error)
- func (c *Client) Download(ctx context.Context, desk, remote string, w io.Writer, opts ...CallOption) (int64, error)
- func (c *Client) DownloadBytes(ctx context.Context, desk, remote string, opts ...CallOption) ([]byte, error)
- func (c *Client) DownloadFile(ctx context.Context, desk, remote, local string, opts ...CallOption) (*CopyResult, error)
- func (c *Client) Exec(ctx context.Context, desk string, req ExecRequest, opts ...CallOption) (*ExecResult, error)
- func (c *Client) ExecStream(ctx context.Context, desk string, req ExecRequest, opts ...CallOption) (*Stream, error)
- func (c *Client) FollowJobLogs(ctx context.Context, desk, name string, o *LogsOptions, opts ...CallOption) (*Stream, error)
- func (c *Client) JobLogs(ctx context.Context, desk, name string, o *LogsOptions, opts ...CallOption) (*JobLogs, error)
- func (c *Client) Jobs(ctx context.Context, desk string, opts ...CallOption) ([]Job, error)
- func (c *Client) KillJob(ctx context.Context, desk, name string, opts ...CallOption) (*Job, error)
- func (c *Client) OpenDownload(ctx context.Context, desk, remote string, opts ...CallOption) (io.ReadCloser, error)
- func (c *Client) Reach(ctx context.Context, desk string, o *ReachOptions, opts ...CallOption) (*ReachLog, error)
- func (c *Client) RevokeToken(ctx context.Context, desk, token string, opts ...CallOption) (*Revoked, error)
- func (c *Client) StartJob(ctx context.Context, desk string, job JobRequest, opts ...CallOption) (*Job, error)
- func (c *Client) Stats(ctx context.Context, desk string, opts ...CallOption) (*StatsReport, error)
- func (c *Client) SupportSession(ctx context.Context, id string, opts ...CallOption) (*SupportSession, error)
- func (c *Client) SupportSessions(ctx context.Context, f *SupportSessionFilter, opts ...CallOption) ([]SupportSession, error)
- func (c *Client) Tokens(ctx context.Context, desk string, opts ...CallOption) ([]TokenInfo, error)
- func (c *Client) Transport() Transport
- func (c *Client) Upload(ctx context.Context, desk, remote string, r io.Reader, opts ...CallOption) (*CopyResult, error)
- func (c *Client) UploadFile(ctx context.Context, local, desk, remote string, opts ...CallOption) (*CopyResult, error)
- func (c *Client) WaitJob(ctx context.Context, desk, name string, timeout time.Duration, ...) (*JobWaitResult, error)
- func (c *Client) Wake(ctx context.Context, desk string, wait time.Duration, opts ...CallOption) (*WakeResult, error)
- func (c *Client) Webhooks(ctx context.Context, opts ...CallOption) ([]Webhook, error)
- type CommandError
- type CopyFailure
- type CopyResult
- type Desk
- type DeskDetail
- type DeskEventData
- type DeskList
- type DiskStat
- type E2EMode
- type Error
- type ErrorKind
- type ExecExit
- type ExecRequest
- type ExecResult
- type Exit
- type FingerprintMismatchError
- type Identity
- type Job
- type JobFinishedData
- type JobLimits
- type JobLogs
- type JobRequest
- type JobWaitResult
- type LogsOptions
- type MintResult
- type MintedToken
- type Option
- func WithAdminToken(t string) Option
- func WithBaseURL(u string) Option
- func WithDeskToken(t string) Option
- func WithE2E(mode E2EMode) Option
- func WithE2EKeys(keys map[string]string) Option
- func WithEnv(env map[string]string) Option
- func WithHTTPClient(h *http.Client) Option
- func WithIdleTimeout(d time.Duration) Option
- func WithResponseTimeout(d time.Duration) Option
- func WithRetry(p RetryPolicy) Option
- func WithSocketPath(p string) Option
- func WithUserAgent(ua string) Option
- func WithWarningHandler(f func(message string)) Option
- type ReachEvent
- type ReachFailure
- type ReachLog
- type ReachOptions
- type ReachSuccess
- type ResponseInfo
- type RetryPolicy
- type Revoked
- type Shell
- type StatsReport
- type Stream
- type SupportSession
- type SupportSessionCreated
- type SupportSessionEventData
- type SupportSessionFilter
- type SupportSessionRequest
- type TokenInfo
- type TokenRequest
- type Transport
- type WakeHints
- type WakeResult
- type Webhook
- type WebhookCreated
- type WebhookEvent
- type WebhookRequest
Constants ¶
const ( ReasonUnauthenticated = "unauthenticated" ReasonMissingScope = "missing_scope" ReasonRateLimited = "rate_limited" ReasonDeskBusy = "desk_busy" ReasonDeskTokenRequired = "desk_token_required" ReasonDeskOptedOut = "desk_opted_out" ReasonDeskTooOld = "desk_too_old" ReasonDeskOpsDisabled = "desk_ops_disabled" ReasonAgentCannotAdmin = "agent_cannot_admin" ReasonUnknownDesk = "unknown_desk" ReasonNoWakePath = "no_wake_path" ReasonNoSuchRoute = "no_such_route" ReasonTooLarge = "too_large" ReasonIsFolder = "is_folder" ReasonIdempotencyReused = "idempotency_key_reused" ReasonIdempotencyInFlight = "idempotency_key_in_flight" ReasonIncomplete = "incomplete" ReasonNetwork = "network" ReasonFingerprintMismatch = "fingerprint_mismatch" // End-to-end encryption. ReasonE2ERequired = "e2e_required" ReasonE2EKeyMismatch = "e2e_key_mismatch" ReasonE2EDecryptFailed = "e2e_decrypt_failed" ReasonE2EMalformed = "e2e_malformed" ReasonE2EUnsealedAnswer = "e2e_unsealed_answer" ReasonE2EUnsupported = "e2e_unsupported" ReasonE2EStale = "e2e_stale" ReasonE2EReplayed = "e2e_replayed" ReasonE2EOpMismatch = "e2e_op_mismatch" // Administrator work (root / SYSTEM) is not available over the API: an // exec asking for it, or a token minted with the `admin` scope, is refused // with this reason. It runs only through `gaiadesk-cli exec --admin`. ReasonAdminNotViaAPI = "admin_not_via_api" ReasonBlockedByOSPolicy = "blocked_by_os_policy" )
Reasons the API, the desk or the SDK give (`error.reason`). Not a closed list: compare with the constants you care about.
const ( // SupportView: the agent sees the shared tab. SupportView = "view" // SupportCobrowse: the agent may also point, highlight, click, scroll // and type inside the page (applied by the embed to its own DOM). SupportCobrowse = "cobrowse" )
Support session modes.
const ( ScopeScreen = "screen" ScopeExec = "exec" ScopeShell = "shell" ScopeCp = "cp" ScopeForward = "forward" ScopeJobs = "jobs" )
Agent token scopes (what a token may do on the desk).
const ( EventDeskOnline = "desk.online" EventDeskOffline = "desk.offline" EventDeskWoke = "desk.woke" EventJobFinished = "job.finished" EventSupportSessionJoined = "support.session.joined" EventSupportSessionEnded = "support.session.ended" )
Webhook event types.
const DefaultBaseURL = "https://api.gaiadesk.net/v1"
DefaultBaseURL is the hosted GaiaDesk API.
const DefaultIdleTimeout = 90 * time.Second
DefaultIdleTimeout is the default WithIdleTimeout: 90 seconds (the API's streams and held waits send a keep-alive every 15 s).
const DefaultResponseTimeout = 16 * time.Minute
DefaultResponseTimeout is the default WithResponseTimeout: 16 minutes, above the API's 15-minute limit on a call (a buffered Exec answers when its command ends).
const FileLimit = 256 * 1024 * 1024
FileLimit is the most one file may be through the API (256 MB); larger files go direct, through gaiadesk-cli.
LocalAPIUnavailable is what a missing socket or pipe means.
const Version = "0.1.2"
Version is this SDK's version.
const WaitForever time.Duration = -1
WaitForever is WaitJob's timeout for "until the job ends" (or the context is done).
const WaitMax = 870 * time.Second
WaitMax is the longest one `GET …/jobs/{name}/wait` holds (870 s); Client.WaitJob waits again for longer.
Variables ¶
var ( ErrUsage = errors.New("gaiadesk: usage") ErrRefused = errors.New("gaiadesk: refused") ErrUnreachable = errors.New("gaiadesk: unreachable") ErrConnectionLost = errors.New("gaiadesk: connection lost") ErrFailed = errors.New("gaiadesk: failed") ErrProtocol = errors.New("gaiadesk: protocol") // ErrInterrupted: the call's context was cancelled (or its stream closed). ErrInterrupted = errors.New("gaiadesk: interrupted") // ErrE2E: the SDK would not send an operation in the clear, or the server // handed out a key other than the pinned one (also an ErrRefused). ErrE2E = errors.New("gaiadesk: end-to-end encryption") // ErrCommand: Exec with Check and a non-zero exit (a *CommandError). ErrCommand = errors.New("gaiadesk: command failed") // ErrFingerprintMismatch: the LAN gateway is not the desk you pinned // (a *FingerprintMismatchError, also an ErrUnreachable). ErrFingerprintMismatch = errors.New("gaiadesk: fingerprint mismatch") )
Sentinel errors for errors.Is: every *Error matches the one for its class, so `errors.Is(err, gaiadesk.ErrRefused)` is true for any refusal.
var ( ErrWebhookSignature = errors.New("gaiadesk: webhook signature does not verify") ErrWebhookTimestamp = errors.New("gaiadesk: webhook timestamp is more than five minutes off") )
Webhook verification failures.
var DefaultRetry = RetryPolicy{MaxAttempts: 3, BaseDelay: 250 * time.Millisecond, MaxDelay: 8 * time.Second, MaxRetryWait: 60 * time.Second}
DefaultRetry is the default policy: three tries, backoff from 250 ms up to 8 s, a Retry-After of up to 60 s waited.
var DefaultScopes = []string{ScopeExec, ScopeCp, ScopeJobs}
DefaultScopes are a new token's scopes when none are given.
var NoRetry = RetryPolicy{MaxAttempts: 1}
NoRetry makes every call once.
Functions ¶
func LocalAPIDir ¶
LocalAPIDir is the directory of the local API's socket and token: $GAIADESK_API_DIR when it is absolute, else <home>/.gaiadesk. goos is runtime.GOOS's form.
func LocalPipeName ¶
LocalPipeName is the local API's Windows pipe: $GAIADESK_API_PIPE, else `\\.\pipe\gaiadesk-api-<user>` (<user>: $USERNAME, else username).
func LocalSocketPath ¶
LocalSocketPath is the local API's Unix socket (macOS, Linux).
func LocalTokenPath ¶
LocalTokenPath is the file holding the desk's local admin token (`gdlocal_` + 64 hex digits).
func NormalizeFingerprint ¶
NormalizeFingerprint reads a SHA-256 certificate fingerprint as the desk shows it (with or without colons or spaces, any case) and writes it as 32 lowercase hex pairs joined by `:`.
func ParseDuration ¶
ParseDuration reads a duration as gaiadesk-cli writes them: `90` (seconds), `30s`, `10m`, `1h30m`, `7d`, `2w`. Days and weeks are 24 and 168 hours.
func PipeUser ¶
PipeUser is the pipe-name form of a user name: lowercased, [a-z0-9._-] kept, the rest `_`, at most 64 characters, `user` if empty.
func SignWebhook ¶
SignWebhook makes a GaiaDesk-Signature header for body at t, as the API does: for testing a webhook handler.
func VerifyWebhook ¶
VerifyWebhook checks a delivery's GaiaDesk-Signature header (`t=<unix seconds>,v1=<hex HMAC-SHA256 of "<t>.<raw body>">`) against the webhook's secret over the raw body, in constant time, and that t is within five minutes of now.
Types ¶
type AuditEvent ¶
type AuditEvent struct {
ID string `json:"id"`
Action string `json:"action"`
Stream string `json:"stream"`
OccurredAtMS int64 `json:"occurred_at_ms"`
Actor struct {
Type string `json:"type"`
ID string `json:"id,omitempty"`
} `json:"actor"`
Target *struct {
Type string `json:"type,omitempty"`
ID string `json:"id,omitempty"`
Name string `json:"name,omitempty"`
} `json:"target,omitempty"`
Metadata json.RawMessage `json:"metadata"`
}
AuditEvent is one audit event (Atlas audit events).
type AuditFilter ¶
type AuditFilter struct {
// Desk: only events about this desk (one of the caller's own).
Desk string
// Actor: only events by this actor id (an email, a token id).
Actor string
// Action: only this action, or every action under it when it ends in
// `.*` (`api.*`).
Action string
// Token: only events by this agent token id or API key id.
Token string
// Since and Until bound when it happened (inclusive; zero: unbounded).
Since, Until time.Time
// Limit is the most events per call (default 100, at most 500).
Limit int
}
AuditFilter narrows the audit trail.
type CallOption ¶
type CallOption func(*callConfig)
CallOption configures one call.
func CaptureResponse ¶
func CaptureResponse(info *ResponseInfo) CallOption
CaptureResponse fills info with what the response's headers said (its request id, rate limit, replay) once the call is answered.
func UseDeskToken ¶
func UseDeskToken(token string) CallOption
UseDeskToken sends this scoped agent token (`gdagt_…`) with this call, instead of the client's.
func WakeFor ¶
func WakeFor(d time.Duration) CallOption
WakeFor rings a sleeping desk and waits up to d (0 to 120 s; the API's `wake_s`, default 60 s) for it before a desk operation.
func WithIdempotencyKey ¶
func WithIdempotencyKey(key string) CallOption
WithIdempotencyKey sends `Idempotency-Key` on a POST: a retry of yours with the same key and the same request within 24 hours gets the first answer again. (The SDK itself never sends a POST again after it may have reached the server, key or not.)
func WithoutRetry ¶
func WithoutRetry() CallOption
WithoutRetry makes this call once, whatever the client's retry policy.
type Chunk ¶
type Chunk struct {
// Stream is "stdout" or "stderr" (a job's log is all "stdout").
Stream string
// Data is the text, as bytes (a character split across chunks arrives
// whole in the later one).
Data []byte
}
Chunk is a piece of a stream's output.
type Class ¶
type Class string
Class is one of the six kinds every GaiaDesk error envelope carries (`error.kind`), the same six gaiadesk-cli prints. Branch on it first, then on Error.Reason where you need finer detail.
const ( ClassUsage Class = "usage" // bad arguments: fix the call ClassRefused Class = "refused" // the desk or the server said no ClassUnreachable Class = "unreachable" // the desk or the server could not be reached ClassConnectionLost Class = "connection_lost" // reached, then the connection went away ClassFailed Class = "failed" // allowed, and it did not succeed ClassProtocol Class = "protocol" // an answer this client cannot use (often a desk too old) )
The six error classes.
type CliError ¶
type CliError struct {
Kind string `json:"kind"`
Message string `json:"message"`
Reason string `json:"reason,omitempty"`
Desk string `json:"desk,omitempty"`
}
CliError is what went wrong, as the API and gaiadesk-cli report it: the object inside `{"error": …}` (and exec's `error`).
type Client ¶
type Client struct {
// contains filtered or unexported fields
}
Client drives GaiaDesk desks through a /v1 API: the hosted one (New), a desk's own (NewLocal), or a desk's LAN gateway (NewLAN). Every method takes a context; cancelling it stops the call. A Client is safe for concurrent use.
func New ¶
New is a client of the hosted GaiaDesk API, authenticated with an Atlas API key (`ak_…`) or a signed-in person's session token. Desk operations from an API key need an agent token too (WithDeskToken or UseDeskToken).
func NewLAN ¶
NewLAN is a client of a desk's LAN gateway (`https://<desk>:7443/v1`, or `https://gaiadesk-<desk id>.local:7443/v1`), its certificate pinned by the SHA-256 fingerprint its Settings show. It takes agent tokens only (WithDeskToken, or UseDeskToken per call). Options: WithDeskToken, WithRetry, WithUserAgent.
func NewLocal ¶
NewLocal is a client of the desk's own API, for code running on the desk: the same desk operations as the hosted API (and Desks, this desk), over its socket or pipe. Options: WithSocketPath, WithAdminToken, WithDeskToken, WithEnv, WithRetry, WithUserAgent.
func (*Client) Audit ¶
func (c *Client) Audit(ctx context.Context, f *AuditFilter, opts ...CallOption) ([]AuditEvent, error)
Audit reads audit events about the caller and their own desks, newest first: `GET /audit`. AuditAll pages through all of them.
func (*Client) AuditAll ¶
func (c *Client) AuditAll(ctx context.Context, f *AuditFilter, opts ...CallOption) iter.Seq2[AuditEvent, error]
AuditAll iterates over every audit event the filter matches, newest first, a page (Limit, default 100) at a time; an error ends the iteration with it.
func (*Client) CreateSupportSession ¶
func (c *Client) CreateSupportSession(ctx context.Context, s SupportSessionRequest, opts ...CallOption) (*SupportSessionCreated, error)
CreateSupportSession creates a support session: `POST /support/sessions`. Hand the result's EmbedToken (shown once) to the customer's page or app; the support team joins with JoinCode.
func (*Client) CreateToken ¶
func (c *Client) CreateToken(ctx context.Context, t TokenRequest, opts ...CallOption) (*MintResult, error)
CreateToken mints a scoped agent token on each desk: `POST /desks/{id}/tokens` once per desk. Token administration is the desk OWNER's (a signed-in person's session, not an API key's agent token). If a later desk fails, the result holds the tokens already minted alongside the error: their secrets are shown once.
func (*Client) CreateWebhook ¶
func (c *Client) CreateWebhook(ctx context.Context, w WebhookRequest, opts ...CallOption) (*WebhookCreated, error)
CreateWebhook subscribes an endpoint: `POST /webhooks`. Keep the result's Secret (it is never shown again) to verify deliveries with VerifyWebhook.
func (*Client) DeleteWebhook ¶
DeleteWebhook unsubscribes (deliveries still queued are dropped): `DELETE /webhooks/{webhook_id}`.
func (*Client) Desk ¶
func (c *Client) Desk(ctx context.Context, desk string, opts ...CallOption) (*DeskDetail, error)
Desk reads one desk, with its reachability, wake hints and end-to-end key: `GET /desks/{id}`.
func (*Client) Desks ¶
Desks lists the desks on the account and its team, online first: `GET /desks` (on the local and lan transports, the desk itself).
func (*Client) Download ¶
func (c *Client) Download(ctx context.Context, desk, remote string, w io.Writer, opts ...CallOption) (int64, error)
Download copies a file on the desk to w, returning the bytes written. On an error, w may hold part of the file.
func (*Client) DownloadBytes ¶
func (c *Client) DownloadBytes(ctx context.Context, desk, remote string, opts ...CallOption) ([]byte, error)
DownloadBytes reads a file on the desk into memory.
func (*Client) DownloadFile ¶
func (c *Client) DownloadFile(ctx context.Context, desk, remote, local string, opts ...CallOption) (*CopyResult, error)
DownloadFile copies a file on the desk to a local file (a local folder, or a path ending in a separator, keeps the remote name). The file appears only once complete.
func (*Client) Exec ¶
func (c *Client) Exec(ctx context.Context, desk string, req ExecRequest, opts ...CallOption) (*ExecResult, error)
Exec runs one command on the desk: `POST /desks/{id}/exec`. A command that ran is a result whatever its exit code; one the desk refused to start (or that never ran) is its typed error. With Check, a non-zero exit is a *CommandError.
func (*Client) ExecStream ¶
func (c *Client) ExecStream(ctx context.Context, desk string, req ExecRequest, opts ...CallOption) (*Stream, error)
ExecStream runs one command on the desk and streams its output: `POST /desks/{id}/exec?stream=1`. The error is the call's failure before the stream started (refused, unreachable, …); a failure after is the stream's Exit. Close the stream (or read it to the end) when done.
func (*Client) FollowJobLogs ¶
func (c *Client) FollowJobLogs(ctx context.Context, desk, name string, o *LogsOptions, opts ...CallOption) (*Stream, error)
FollowJobLogs streams a job's output as it is written, until the job ends: `GET /desks/{id}/jobs/{name}/logs?follow=1`. Closing the stream stops following; the job goes on.
func (*Client) JobLogs ¶
func (c *Client) JobLogs(ctx context.Context, desk, name string, o *LogsOptions, opts ...CallOption) (*JobLogs, error)
JobLogs reads a job and the end of its output: `GET /desks/{id}/jobs/{name}/logs`.
func (*Client) KillJob ¶
KillJob stops a job and everything it started: `DELETE /desks/{id}/jobs/{name}`.
func (*Client) OpenDownload ¶
func (c *Client) OpenDownload(ctx context.Context, desk, remote string, opts ...CallOption) (io.ReadCloser, error)
OpenDownload opens a file on the desk for reading: `GET /desks/{id}/files?path=`. Read it to io.EOF: a transfer that breaks off is an error (ErrConnectionLost), never a clean short file. Close it.
func (*Client) Reach ¶
func (c *Client) Reach(ctx context.Context, desk string, o *ReachOptions, opts ...CallOption) (*ReachLog, error)
Reach reads the desk's online and offline history, newest first: `GET /desks/{id}/reach`.
func (*Client) RevokeToken ¶
func (c *Client) RevokeToken(ctx context.Context, desk, token string, opts ...CallOption) (*Revoked, error)
RevokeToken revokes an agent token by id or name; its live sessions and jobs end: `DELETE /desks/{id}/tokens/{token_id}`.
func (*Client) StartJob ¶
func (c *Client) StartJob(ctx context.Context, desk string, job JobRequest, opts ...CallOption) (*Job, error)
StartJob starts a background job: `POST /desks/{id}/jobs`. It runs under the desk's GaiaDesk and outlives the call; its end is the `job.finished` webhook (or WaitJob).
func (*Client) Stats ¶
func (c *Client) Stats(ctx context.Context, desk string, opts ...CallOption) (*StatsReport, error)
Stats reads the desk's figures (CPU, memory, disks, running jobs): `GET /desks/{id}/stats`.
func (*Client) SupportSession ¶
func (c *Client) SupportSession(ctx context.Context, id string, opts ...CallOption) (*SupportSession, error)
SupportSession reads one support session's state: `GET /support/sessions/{session_id}`.
func (*Client) SupportSessions ¶
func (c *Client) SupportSessions(ctx context.Context, f *SupportSessionFilter, opts ...CallOption) ([]SupportSession, error)
SupportSessions lists the support sessions of the caller's account and team, newest first (the console's queue): `GET /support/sessions`.
func (*Client) Tokens ¶
Tokens lists the desk's agent tokens (never their secrets): `GET /desks/{id}/tokens`.
func (*Client) Upload ¶
func (c *Client) Upload(ctx context.Context, desk, remote string, r io.Reader, opts ...CallOption) (*CopyResult, error)
Upload writes r's bytes to remote, a file on the desk (relative paths start in the desk user's home, or a confined token's folder; a path that names an existing folder receives it under that folder's last name): `PUT /desks/{id}/files?path=`. At most FileLimit (256 MB). An io.ReadSeeker (an *os.File, a *bytes.Reader) is streamed; any other reader is read into memory first, as the API needs the size up front.
func (*Client) UploadFile ¶
func (c *Client) UploadFile(ctx context.Context, local, desk, remote string, opts ...CallOption) (*CopyResult, error)
UploadFile copies a local file to the desk. A remote ending in `/` (or "") is a folder: the file keeps its name.
func (*Client) WaitJob ¶
func (c *Client) WaitJob(ctx context.Context, desk, name string, timeout time.Duration, opts ...CallOption) (*JobWaitResult, error)
WaitJob waits until a job is no longer running, or timeout passes (0: answer at once; WaitForever: until it ends): the job as it ended, or (TimedOut) as it stands. The API holds one wait at most WaitMax, so a longer one waits again. A held answer that failed after its 200 began is its typed error, as any other failure.
func (*Client) Wake ¶
func (c *Client) Wake(ctx context.Context, desk string, wait time.Duration, opts ...CallOption) (*WakeResult, error)
Wake rings the desk's doorbell and asks its LAN siblings to Wake-on-LAN it; with wait > 0, waits up to that long (at most 90 s) for it to come online and says whether it woke: `POST /desks/{id}/wake`. A desk with nothing to ring is ErrUnreachable, reason ReasonNoWakePath.
type CommandError ¶
type CommandError struct {
// Err says how (class failed; ExitCode is the command's exit).
Err *Error
Result *ExecResult
}
CommandError is Client.Exec with Check set when the command exited non-zero (or timed out): the result is in Result.
func (*CommandError) Is ¶
func (e *CommandError) Is(target error) bool
Is matches ErrCommand and ErrFailed.
type CopyFailure ¶
CopyFailure is one file that failed to copy.
type CopyResult ¶
type CopyResult struct {
Direction string `json:"direction"`
Desk string `json:"desk"`
Destination string `json:"destination"`
Files uint32 `json:"files"`
Dirs uint32 `json:"dirs"`
Bytes uint64 `json:"bytes"`
ResumedBytes uint64 `json:"resumed_bytes"`
Failed []CopyFailure `json:"failed"`
Seconds float64 `json:"seconds"`
}
CopyResult is what a copy did: `cp --json`.
type Desk ¶
type Desk struct {
DeskID string `json:"desk_id"`
Name string `json:"name,omitempty"`
Online bool `json:"online"`
OS string `json:"os,omitempty"`
AppVersion string `json:"app_version,omitempty"`
Owner string `json:"owner,omitempty"`
Sources []string `json:"sources"`
LastSeen *int64 `json:"last_seen,omitempty"`
SignalIdleSecs *uint64 `json:"signal_idle_secs,omitempty"`
Anytime *bool `json:"anytime,omitempty"`
Reachable *bool `json:"reachable,omitempty"`
LastOK *ReachSuccess `json:"last_ok,omitempty"`
LastFailure *ReachFailure `json:"last_failure,omitempty"`
// OfflineSince is when it went offline (Unix seconds), with
// OfflineReason (`closed`, `silent`, `error`, `updating`,
// `server-restart`, `id-changed`, `unknown`) and its text.
OfflineSince *int64 `json:"offline_since,omitempty"`
OfflineReason string `json:"offline_reason,omitempty"`
OfflineReasonText string `json:"offline_reason_text,omitempty"`
OfflineDetail string `json:"offline_detail,omitempty"`
// Features is what it takes now, while online: `desk_op`, `desk_op_e2e`.
Features []string `json:"features,omitempty"`
// E2EPub is its end-to-end X25519 public key (base64url) while online
// and able to open sealed operations.
E2EPub string `json:"e2e_pub,omitempty"`
// E2ERequired: its owner requires end-to-end encryption for API commands.
E2ERequired bool `json:"e2e_required,omitempty"`
}
Desk is one desk as `GET /desks` lists it: the CLI's `devices --json` row plus the reach log's word on an offline one and its end-to-end key.
type DeskDetail ¶
DeskDetail is `GET /desks/{id}`: one desk, with its wake hints.
type DeskEventData ¶
type DeskEventData struct {
Desk struct {
DeskID string `json:"desk_id"`
Owner string `json:"owner"`
Reason string `json:"reason"`
ReasonText string `json:"reason_text"`
Version string `json:"version,omitempty"`
// WokeAfterMS is desk.woke's: how long after the ring it came online.
WokeAfterMS *int64 `json:"woke_after_ms,omitempty"`
} `json:"desk"`
}
DeskEventData is the data of desk.online, desk.offline and desk.woke.
type DeskList ¶
type DeskList struct {
Devices []Desk `json:"devices"`
Sources []string `json:"sources"`
Notes []string `json:"notes"`
Identity *Identity `json:"identity,omitempty"`
}
DeskList is `GET /desks`: the CLI's `devices --json` object.
type DiskStat ¶
type DiskStat struct {
Mount string `json:"mount"`
TotalMB uint64 `json:"total_mb"`
FreeMB uint64 `json:"free_mb"`
}
DiskStat is one disk of a desk.
type E2EMode ¶
type E2EMode string
E2EMode is the end-to-end encryption of desk operations on the hosted API.
const ( // E2EAuto (default): sealed when the desk lists a key (or requires it); // else in the clear, with a warning once per desk. E2EAuto E2EMode = "auto" // E2ERequire: never in the clear; a desk without a key is woken and // asked again, else the call fails (ErrE2E) and nothing is sent. E2ERequire E2EMode = "require" // E2EOff: never sealed. E2EOff E2EMode = "off" )
The modes.
type Error ¶
type Error struct {
// Class is the envelope's kind: one of the six ("" for the SDK's own
// interrupted and local errors).
Class Class
// Kind is the SDK's finest kind (see ErrorKind).
Kind ErrorKind
// Message is what went wrong, for a person.
Message string
// Reason is the finer cause (`offline`, `rate_limited`, `e2e_required`,
// `admin_not_via_api`, …), or "".
Reason string
// Desk is the desk the error concerned, when the API said.
Desk string
// Op is the request: `POST /desks/123456789/exec`.
Op string
// Status is the HTTP status of the failed request (0 when none was
// answered; on a held answer, the status it would have had).
Status int
// RequestID is the request's id (`req_…`), to quote to support.
RequestID string
// RetryAfter is how long the API asked to wait before retrying (429).
RetryAfter time.Duration
// ExitCode is what gaiadesk-cli exits with for this error (254 refused,
// 1 failed, 130 interrupted, 255 the rest), for CLI parity.
ExitCode int
// Body is the raw error body, when there was one.
Body json.RawMessage
// Err is the underlying cause (a network error, the context's error), or nil.
Err error
// contains filtered or unexported fields
}
Error is every failure the SDK returns: the API's error envelope (`{"error": {"kind", "message", "reason", "desk", "request_id"}}`), or the SDK's own in the same terms.
type ErrorKind ¶
type ErrorKind string
ErrorKind is the SDK's finest word on an error: the envelope's reason when it is one of the kinds below (so `offline` stays `offline`), else its Class. It matches the TypeScript and Python SDKs' `kind`.
const ( KindUsage ErrorKind = "usage" KindOffline ErrorKind = "offline" KindUnknownDesk ErrorKind = "unknown_desk" KindNotOnline ErrorKind = "not_online" KindRefused ErrorKind = "refused" KindNetwork ErrorKind = "network" KindNotSignedIn ErrorKind = "not_signed_in" KindTimeout ErrorKind = "timeout" KindConnectionLost ErrorKind = "connection_lost" KindLocal ErrorKind = "local" KindFailed ErrorKind = "failed" KindInterrupted ErrorKind = "interrupted" KindProtocol ErrorKind = "protocol" KindUnreachable ErrorKind = "unreachable" )
The SDK's kinds.
type ExecExit ¶
type ExecExit struct {
Exit int `json:"exit"`
RemoteCode *int `json:"remote_code"`
DurationMS uint64 `json:"duration_ms"`
Desk string `json:"desk"`
Route string `json:"route,omitempty"`
Mode string `json:"mode,omitempty"`
Shell string `json:"shell,omitempty"`
TimedOut bool `json:"timed_out"`
Notes []string `json:"notes"`
Error *CliError `json:"error"`
}
ExecExit is the end of a streamed run, without its output.
type ExecRequest ¶
type ExecRequest struct {
// Command is ONE command line, given to the desk's shell verbatim.
Command string
// Argv is an argument vector instead: each entry quoted for the shell,
// so the program receives exactly it (ShellNone: run directly).
Argv []string
// Shell runs the command (default: the desk's own).
Shell Shell
// Cwd is the directory it runs in (relative: from the desk user's home,
// or a confined token's folder).
Cwd string
// Env are environment variables for the command (never logged by the
// server or the desk: at most their names).
Env map[string]string
// Stdin is read whole and sent up front, as text (UTF-8). The API takes
// no stdin while the command runs.
Stdin io.Reader
// Timeout stops the command after this long (rounded up to seconds;
// 0: the API's limit, 15 minutes).
Timeout time.Duration
// Check makes a non-zero exit (or a timeout) a *CommandError.
Check bool
}
ExecRequest is one command to run on a desk (the API's ExecSpec).
type ExecResult ¶
type ExecResult struct {
Exit int `json:"exit"`
RemoteCode *int `json:"remote_code"`
Stdout string `json:"stdout"`
Stderr string `json:"stderr"`
DurationMS uint64 `json:"duration_ms"`
Desk string `json:"desk"`
Route string `json:"route,omitempty"`
Mode string `json:"mode,omitempty"`
Shell string `json:"shell,omitempty"`
TimedOut bool `json:"timed_out"`
Truncated bool `json:"truncated"`
Notes []string `json:"notes"`
Error *CliError `json:"error"`
}
ExecResult is how a command ended: `exec --json`. Exit is what gaiadesk-cli exits with (the command's code, 124 timed out, 130 interrupted, 254 refused); Error is nil when the command ran and ended on its own.
type Exit ¶
type Exit struct {
// ExitCode is what gaiadesk-cli would exit with: the command's own code
// (exec), 0 for a log follow that ended or was stopped, 130 when the
// stream was closed or its context cancelled, 254 refused, 255 the rest.
ExitCode int
// StderrTail is the reason, when it failed (or what ended a log follow).
StderrTail string
// Result is how the command ended, without its output (exec streams).
Result *ExecExit
// Job is the job as it ended (a log follow's `end`).
Job *Job
// Error is why it never ran, was stopped or broke off, or nil.
Error *CliError
}
Exit is how a stream ended.
type FingerprintMismatchError ¶
type FingerprintMismatchError struct {
// Err is the error (class unreachable, reason fingerprint_mismatch).
Err *Error
// Expected is the pinned fingerprint, Actual the one the server
// presented (`ab:cd:…`).
Expected, Actual string
}
FingerprintMismatchError is the LAN gateway's certificate not matching the pinned fingerprint: it is not the desk you pinned. Do not proceed.
func (*FingerprintMismatchError) Error ¶
func (e *FingerprintMismatchError) Error() string
Error is the *Error's message.
func (*FingerprintMismatchError) Is ¶
func (e *FingerprintMismatchError) Is(target error) bool
Is matches ErrFingerprintMismatch and ErrUnreachable.
func (*FingerprintMismatchError) Unwrap ¶
func (e *FingerprintMismatchError) Unwrap() error
Unwrap returns the *Error.
type Job ¶
type Job struct {
Name string `json:"name"`
Command string `json:"command"`
State string `json:"state"`
StartedAtMS uint64 `json:"started_at_ms"`
EndedAtMS *uint64 `json:"ended_at_ms,omitempty"`
ExitCode *int `json:"exit_code,omitempty"`
PID *uint32 `json:"pid,omitempty"`
Reason string `json:"reason,omitempty"`
By string `json:"by,omitempty"`
LogBytes uint64 `json:"log_bytes,omitempty"`
Limits *JobLimits `json:"limits,omitempty"`
Enforcement []string `json:"enforcement,omitempty"`
}
Job is a background job.
type JobFinishedData ¶
type JobFinishedData struct {
Desk struct {
DeskID string `json:"desk_id"`
Owner string `json:"owner"`
} `json:"desk"`
Job Job `json:"job"`
}
JobFinishedData is the data of job.finished.
type JobLimits ¶
type JobLimits struct {
Priority string `json:"priority,omitempty"`
CPUPercent *uint32 `json:"cpu_percent,omitempty"`
MemMB *uint64 `json:"mem_mb,omitempty"`
KeepAwake *bool `json:"keep_awake,omitempty"`
}
JobLimits are a job's resource caps.
type JobRequest ¶
type JobRequest struct {
// Name names the job: letters, digits, . _ - (not starting with -).
Name string
// Command is the command line (or Argv its pieces).
Command string
Argv []string
// Cwd is the directory the job starts in on the desk.
Cwd string
// Shell runs the command (default: `sh -c` on macOS/Linux, `cmd /c` on
// Windows; never ShellNone or ShellDefault).
Shell Shell
// Env are environment variables for the job (never logged by the desk).
Env map[string]string
// Priority is "low", "normal" or "high".
Priority string
// CPUPercent caps its share of the whole machine, 1 to 100 (0: none).
CPUPercent int
// MemMB caps its memory in megabytes (0: none).
MemMB uint64
// KeepAwake keeps the desk awake while it runs (nil: the desk's default).
KeepAwake *bool
}
JobRequest starts a background job (the API's JobSpec, as `gaiadesk-cli run --detach`).
type JobWaitResult ¶
JobWaitResult is the job as it ended or, TimedOut, as it stands, still running. Its ExitCode is a result, not an error.
type LogsOptions ¶
type LogsOptions struct {
// Tail is the last this many bytes (0: all the desk keeps).
Tail int
}
LogsOptions says how much of a job's output to read.
type MintResult ¶
type MintResult struct {
Tokens []MintedToken `json:"tokens"`
}
MintResult is Client.CreateToken: one token per desk.
type MintedToken ¶
type MintedToken struct {
Desk string `json:"desk"`
Token TokenInfo `json:"token"`
Secret string `json:"secret"`
}
MintedToken is one desk's new token and its secret (shown once).
type Option ¶
type Option func(*config)
Option configures a Client.
func WithAdminToken ¶
WithAdminToken sets the desk's local admin token (`gdlocal_…`; NewLocal; default: read from its file on each request).
func WithBaseURL ¶
WithBaseURL sets the API's base URL (default DefaultBaseURL), for a local signal server or a staging API.
func WithDeskToken ¶
WithDeskToken sets the scoped agent token (`gdagt_…`) sent as X-GaiaDesk-Desk-Token with every desk operation; the desk verifies it. A call may give its own with UseDeskToken.
func WithE2E ¶
WithE2E sets end-to-end encryption of desk operations (hosted API only): E2EAuto (default), E2ERequire or E2EOff.
func WithE2EKeys ¶
WithE2EKeys pins desk keys, {deskID: e2e_pub (base64url)}: a different key from the server is refused, and a pinned key seals while the server lists none.
func WithEnv ¶
WithEnv sets the environment the local transport's defaults are read from (GAIADESK_API_DIR, GAIADESK_API_PIPE, USERNAME; default: this process's).
func WithHTTPClient ¶
WithHTTPClient sets the http.Client of the hosted API transport (default: one of the SDK's own). Do not give it a Timeout: streams and held waits last long; use contexts. The SDK's response and idle timeouts hold for it too.
func WithIdleTimeout ¶ added in v0.1.1
WithIdleTimeout sets the longest silence while reading an answer's body (a JSON result, a download, an event stream, a held wait): a limit on each read, not on the whole body, so a long download that keeps flowing never times out (default DefaultIdleTimeout; 0: no limit). Exceeded: ErrConnectionLost, kind timeout (a Stream ends with it in its Exit); it is not retried.
func WithResponseTimeout ¶ added in v0.1.1
WithResponseTimeout sets the longest wait for an answer to begin (its status and headers), sending the request (and its body) included (default DefaultResponseTimeout; 0: no limit). Exceeded: ErrUnreachable, kind timeout; it is not retried.
func WithRetry ¶
func WithRetry(p RetryPolicy) Option
WithRetry sets the retry policy (default DefaultRetry). NoRetry turns retries off.
func WithSocketPath ¶
WithSocketPath sets the local API's socket path or pipe name (NewLocal; default: see LocalSocketPath and LocalPipeName).
func WithUserAgent ¶
WithUserAgent sets the User-Agent (default `gaiadesk-go/<Version>`).
func WithWarningHandler ¶
WithWarningHandler sets where the SDK's warnings go (default: the log package's standard logger).
type ReachEvent ¶
type ReachEvent struct {
At int64 `json:"at"`
Online bool `json:"online"`
Reason string `json:"reason"`
ReasonText string `json:"reason_text"`
Detail string `json:"detail,omitempty"`
Version string `json:"version,omitempty"`
}
ReachEvent is one online/offline transition of a desk.
type ReachFailure ¶
type ReachFailure struct {
At int64 `json:"at"`
Kind string `json:"kind"`
Message string `json:"message"`
}
ReachFailure is a desk's last failed connection, as the CLI keeps it.
type ReachLog ¶
type ReachLog struct {
DeskID string `json:"desk_id"`
Since int64 `json:"since"`
Events []ReachEvent `json:"events"`
}
ReachLog is `GET /desks/{id}/reach`: transitions, newest first.
type ReachOptions ¶
type ReachOptions struct {
// Since is the oldest transition (default seven days ago; the log keeps
// thirty).
Since time.Time
// Limit is the most transitions, newest first (default 200, at most 1000).
Limit int
}
ReachOptions bound a desk's reach log.
type ReachSuccess ¶
type ReachSuccess struct {
At int64 `json:"at"`
Route string `json:"route"`
ConnectMS *uint64 `json:"connect_ms,omitempty"`
RTTMS *uint64 `json:"rtt_ms,omitempty"`
}
ReachSuccess is a desk's last successful connection, as the CLI keeps it.
type ResponseInfo ¶
type ResponseInfo struct {
// Status is the HTTP status.
Status int
// RequestID is the request's id (`req_…`), to quote to support.
RequestID string
// RateLimitLimit, RateLimitRemaining and RateLimitReset are the key's
// budget (requests per window, left, seconds until it resets); -1 when
// the response did not say.
RateLimitLimit, RateLimitRemaining, RateLimitReset int
// IdempotentReplayed: this answer is a stored one, replayed for a
// repeated Idempotency-Key.
IdempotentReplayed bool
// Held: the 200 was sent before its outcome was known (a held wait).
Held bool
// Sealed: the operation went end-to-end encrypted.
Sealed bool
}
ResponseInfo is what a response's headers said.
type RetryPolicy ¶
type RetryPolicy struct {
// MaxAttempts is the most tries in all: 3 (two retries) by default; 1
// (or 0) turns retries off.
MaxAttempts int
// BaseDelay is the first backoff (250 ms by default); each next one
// doubles, up to MaxDelay.
BaseDelay time.Duration
// MaxDelay caps a backoff (8 s by default).
MaxDelay time.Duration
// MaxRetryWait is the longest Retry-After waited (60 s by default; 0
// also means 60 s). A longer one is returned as the error at once.
MaxRetryWait time.Duration
}
RetryPolicy says which failed calls the SDK tries again, and when. The rule (the same in every GaiaDesk SDK): a request is sent again only when that cannot run anything twice.
- The connection was never made (DNS, refused, the TLS handshake, a missing socket or pipe): any method; nothing was sent. A connect that times out, or a certificate that does not verify, is not retried.
- The connection was lost after sending, or the answer was 502, 503 or 504: GETs only. A 503 saying the API or desk operations are switched off is not retried.
- 429 (`rate_limited`, `desk_busy`) and 409 `idempotency_key_in_flight`: any method; the server refused it before acting.
Timeouts are never retried, nor anything whose answer has begun; an Idempotency-Key does not make a call retryable. 429 and 503 wait for Retry-After (one longer than MaxRetryWait is not waited: the error carries it); otherwise the wait is min(MaxDelay, BaseDelay·2ⁿ) times a random 0.5–1.0. Desk operations sealed end to end are sealed afresh for each try.
type Revoked ¶
type Revoked struct {
Revoked string `json:"revoked"`
StoppedSessions uint32 `json:"stopped_sessions"`
}
Revoked is `DELETE /desks/{id}/tokens/{token_id}`.
type Shell ¶
type Shell string
Shell is the shell a command runs under.
const ( ShellDefault Shell = "default" ShellNone Shell = "none" ShellSh Shell = "sh" ShellBash Shell = "bash" ShellZsh Shell = "zsh" ShellCmd Shell = "cmd" ShellPwsh Shell = "pwsh" ShellPowerShell Shell = "powershell" )
The shells. ShellDefault is the desk's own (login shell on macOS/Linux, cmd.exe on Windows); ShellNone runs the first argument as the program. ShellPowerShell is the same as ShellPwsh (sent as `pwsh`).
type StatsReport ¶
type StatsReport struct {
Desk string `json:"desk"`
Hostname string `json:"hostname"`
OS string `json:"os"`
OSVersion string `json:"os_version,omitempty"`
CPUPercent float64 `json:"cpu_percent"`
CPUs uint32 `json:"cpus"`
Load []float64 `json:"load,omitempty"`
MemTotalMB uint64 `json:"mem_total_mb"`
MemFreeMB uint64 `json:"mem_free_mb"`
UptimeSecs uint64 `json:"uptime_secs"`
JobsRunning uint32 `json:"jobs_running"`
Disks []DiskStat `json:"disks,omitempty"`
}
StatsReport is a desk's figures: `stats --json`.
type Stream ¶
type Stream struct {
// contains filtered or unexported fields
}
Stream is a running command (ExecStream) or a log follow (FollowJobLogs): its output as it comes (Recv, Chunks, Copy), then its Exit. Recv is not safe for concurrent use; Close may be called from any goroutine.
func (*Stream) Chunks ¶
Chunks iterates over the output; the iteration ends with the stream (Exit then says how).
func (*Stream) Close ¶
Close stops the stream: the request is closed (the server stops the command, or stops following the job). The Exit is 130 interrupted unless it had already ended.
func (*Stream) Copy ¶
Copy writes the output to stdout and stderr (either may be nil to discard) until the stream ends, and returns its Exit. An error writing stops the stream and is returned.
type SupportSession ¶
type SupportSession struct {
ID string `json:"id"`
State string `json:"state"`
Mode string `json:"mode"`
Customer map[string]any `json:"customer"`
CustomerPresent bool `json:"customer_present"`
CustomerVerified bool `json:"customer_verified"`
JoinCode string `json:"join_code"`
JoinURL string `json:"join_url"`
DeskID string `json:"desk_id,omitempty"`
Origin string `json:"origin,omitempty"`
Owner string `json:"owner"`
CreatedAt int64 `json:"created_at"`
ExpiresAt int64 `json:"expires_at"`
JoinedAt *int64 `json:"joined_at,omitempty"`
JoinedBy string `json:"joined_by,omitempty"`
EndedAt *int64 `json:"ended_at,omitempty"`
EndReason string `json:"end_reason,omitempty"`
}
SupportSession is a support session for the web embed SDK.
type SupportSessionCreated ¶
type SupportSessionCreated struct {
SupportSession
EmbedToken string `json:"embed_token"`
}
SupportSessionCreated is a new session with its embed token (shown once).
type SupportSessionEventData ¶
type SupportSessionEventData struct {
SupportSession SupportSession `json:"support_session"`
}
SupportSessionEventData is the data of support.session.joined and support.session.ended (never the join code, the desk or the embed token).
type SupportSessionFilter ¶
type SupportSessionFilter struct {
// All adds ended and expired sessions to the open ones.
All bool
// Limit is the most sessions (default 50, at most 200).
Limit int
}
SupportSessionFilter narrows the support sessions listed.
type SupportSessionRequest ¶
type SupportSessionRequest struct {
// Mode is SupportView (default) or SupportCobrowse.
Mode string
// Customer is who the customer is, as the company knows them: at most 16
// fields of short strings, numbers or booleans (never in the audit trail).
Customer map[string]any
// ExpiresIn ends the session after this long (60 s to 24 h; default 1 h).
ExpiresIn time.Duration
// Origin is the page origin the embed must run on
// (`https://app.example.com`; `http://` only for localhost). Leave it
// out for the native (desktop) embed.
Origin string
}
SupportSessionRequest creates a support session for the web embed SDK.
type TokenInfo ¶
type TokenInfo struct {
ID string `json:"id"`
Label string `json:"label"`
IssuedAtMS uint64 `json:"issued_at_ms"`
ExpiresAtMS uint64 `json:"expires_at_ms"`
LastUsedMS *uint64 `json:"last_used_ms,omitempty"`
Scopes []string `json:"scopes,omitempty"`
Cwd string `json:"cwd,omitempty"`
LowPriv bool `json:"low_priv,omitempty"`
Revoked bool `json:"revoked,omitempty"`
}
TokenInfo is an agent token as the desk describes it (never its secret).
type TokenRequest ¶
type TokenRequest struct {
// Desks to mint a token on.
Desks []string
// Name names the token (required).
Name string
// Expires is its lifetime (rounded up to seconds; default 7 days).
Expires time.Duration
// Scopes it holds (default DefaultScopes).
Scopes []string
// Cwd confines its work to this directory on the desk.
Cwd string
// LowPriv runs its work as the desk's low-privilege agent user, or refuses.
LowPriv bool
}
TokenRequest mints scoped agent tokens, one per desk, under one name.
type Transport ¶
type Transport string
Transport is how a Client reaches a /v1 API.
const ( // TransportAPI is the hosted API (New). TransportAPI Transport = "api" // TransportLocal is the desk's own API over its Unix socket or named // pipe, for code running on the desk (NewLocal). TransportLocal Transport = "local" // TransportLAN is a desk's LAN gateway over pinned TLS (NewLAN). TransportLAN Transport = "lan" )
The transports.
type WakeHints ¶
type WakeHints struct {
DoorbellSockets int `json:"doorbell_sockets"`
LANWake bool `json:"lan_wake"`
}
WakeHints say how a desk could be woken now.
type WakeResult ¶
type WakeResult struct {
DeskID string `json:"desk_id"`
Online bool `json:"online"`
Woke bool `json:"woke"`
AlreadyOnline bool `json:"already_online"`
Rang struct {
Doorbell int `json:"doorbell"`
LANHelpers int `json:"lan_helpers"`
} `json:"rang"`
WaitedMS int64 `json:"waited_ms"`
}
WakeResult is `POST /desks/{id}/wake`.
type Webhook ¶
type Webhook struct {
ID string `json:"id"`
URL string `json:"url"`
Events []string `json:"events"`
Description string `json:"description"`
CreatedAt int64 `json:"created_at"`
}
Webhook is a webhook subscription (never its secret).
type WebhookCreated ¶
WebhookCreated is a new subscription with its signing secret (shown once).
type WebhookEvent ¶
type WebhookEvent struct {
ID string `json:"id"`
Type string `json:"type"`
Created int64 `json:"created"`
Data json.RawMessage `json:"data"`
}
WebhookEvent is one delivery. ID is stable across retries: de-duplicate by it. Data's shape depends on Type: DeskEventData for desk.*, JobFinishedData for job.finished, SupportSessionEventData for support.session.*.
func ParseWebhook ¶
func ParseWebhook(secret, signature string, body []byte) (*WebhookEvent, error)
ParseWebhook verifies a delivery (VerifyWebhook, against now) and reads it.
func (*WebhookEvent) DecodeData ¶
func (e *WebhookEvent) DecodeData(v any) error
DecodeData unmarshals the event's data into v (one of the *Data types).
type WebhookRequest ¶
type WebhookRequest struct {
// URL is an `https://` URL on the public internet.
URL string
// Events to deliver (at least one): EventDeskOnline, ….
Events []string
// Description, at most 200 characters.
Description string
}
WebhookRequest subscribes an HTTPS endpoint to events.
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
examples
|
|
|
exec
command
Run a command on a desk, then stream another one's output as it runs.
|
Run a command on a desk, then stream another one's output as it runs. |
|
files
command
Copy a file to a desk and back.
|
Copy a file to a desk and back. |
|
jobs
command
Start a background job, follow its log, and wait for it.
|
Start a background job, follow its log, and wait for it. |
|
local
command
On a desk: drive it through the GaiaDesk app's own API (no server, no internet), with the desk's local admin token found beside the socket.
|
On a desk: drive it through the GaiaDesk app's own API (no server, no internet), with the desk's local admin token found beside the socket. |
|
webhook
command
Receive GaiaDesk webhook deliveries, verifying each one.
|
Receive GaiaDesk webhook deliveries, verifying each one. |
|
internal
|
|
|
e2e
Package e2e is the crypto of end-to-end encrypted desk operations, v1: the caller's side (seal a request, seal input, open events) and, for tests and mocks, the desk's side (open a request, seal events, open input).
|
Package e2e is the crypto of end-to-end encrypted desk operations, v1: the caller's side (seal a request, seal input, open events) and, for tests and mocks, the desk's side (open a request, seal events, open input). |
|
mockapi
Package mockapi is a mock of GaiaDesk's /v1 API AND the desks behind it, for the SDK's tests: every route of the contract, plaintext and end-to-end encrypted desk operations (each desk holds an X25519 key, opens sealed requests, runs canned operations and seals its events back), held waits, SSE written in pieces, error envelopes, rate limits, and the desk-served variants (local: the admin token; lan: agent tokens only).
|
Package mockapi is a mock of GaiaDesk's /v1 API AND the desks behind it, for the SDK's tests: every route of the contract, plaintext and end-to-end encrypted desk operations (each desk holds an X25519 key, opens sealed requests, runs canned operations and seals its events back), held waits, SSE written in pieces, error envelopes, rate limits, and the desk-served variants (local: the admin token; lan: agent tokens only). |