Documentation
¶
Overview ¶
Package client is the native Go HTTP client for a Debuglet dispatcher. It runs on the researcher's machine, talks to the dispatcher's existing HTTP API and supports TEST-funded submissions only. It never imports server internals; the wire shapes below mirror the dispatcher's JSON keys.
The guest-side WASI SDK is the separate package pkg/debuglet.
Index ¶
- Constants
- type Account
- type Client
- func (c *Client) Cancel(ctx context.Context, id, executorID string) error
- func (c *Client) Connection(ctx context.Context) (ConnectionInfo, error)
- func (c *Client) CreateAccount(ctx context.Context, name string) (Account, error)
- func (c *Client) Login(ctx context.Context, accountKey string) (Session, error)
- func (c *Client) Logout(ctx context.Context) error
- func (c *Client) Logs(ctx context.Context, id string, options LogOptions) (LogPage, error)
- func (c *Client) Nodes(ctx context.Context) ([]Node, error)
- func (c *Client) Recover(ctx context.Context, recoveryCode string) (Account, error)
- func (c *Client) Status(ctx context.Context, id string) (State, error)
- func (c *Client) SubmitTEST(ctx context.Context, batch *PreparedBatch) (Submission, error)
- func (c *Client) Version(ctx context.Context) (ServerVersion, error)
- func (c *Client) Whoami(ctx context.Context) (User, error)
- func (c *Client) WithCredential(token string) (*Client, error)
- type ConnectionInfo
- type HTTPError
- type LogEntry
- type LogOptions
- type LogPage
- type Node
- type Options
- type Policy
- type PreparedBatch
- type Request
- type ServerVersion
- type Session
- type State
- type Submission
- type SubmissionError
- type User
Constants ¶
const ( // CodeInvalidRequest is a malformed or incomplete request. CodeInvalidRequest = "invalid_request" // CodeInvalidPolicy is a policy that cannot be priced or scheduled. CodeInvalidPolicy = "invalid_policy" // CodeUnknownExecutor names an executor that is not registered. CodeUnknownExecutor = "unknown_executor" // CodeIntentMismatch is a submission whose debuglets differ from the ones // the payment intent was created for. CodeIntentMismatch = "intent_mismatch" // CodePaymentIncomplete is a submission for a transaction that is not paid. CodePaymentIncomplete = "payment_incomplete" // CodeUnsupportedPaymentMethod is a payment method the API does not admit. CodeUnsupportedPaymentMethod = "unsupported_payment_method" // CodePaymentsDisabled is a chain payment method while blockchain payments // are disabled. CodePaymentsDisabled = "payments_disabled" // CodeUnsupportedAPIVersion is APIVersion being unavailable on that server. CodeUnsupportedAPIVersion = "unsupported_api_version" // It is the failure a client answers by logging in again. CodeUnauthorized = "unauthorized" // CodeForbidden is an authenticated account that may not perform the // operation. Logging in again does not help; another account is needed. CodeForbidden = "forbidden" // CodeNotFound is a debuglet, user or executor that does not exist. CodeNotFound = "not_found" // CodeCapacityExhausted is a batch the scheduler cannot admit. CodeCapacityExhausted = "capacity_exhausted" // CodeCancelRefused is a cancellation the dispatcher did not accept. CodeCancelRefused = "cancel_refused" // CodeMethodNotAllowed is a method the route does not serve. CodeMethodNotAllowed = "method_not_allowed" // CodeUnsupportedMediaType is a body representation the route does not read. CodeUnsupportedMediaType = "unsupported_media_type" // CodePayloadTooLarge is a body beyond the accepted size. CodePayloadTooLarge = "payload_too_large" // CodeInternal is a failure inside the dispatcher, with no detail exposed. CodeInternal = "internal_error" CodeUnavailable = "service_unavailable" )
Documented failure codes of the dispatcher's HTTP API. They are the stable part of an error: a client selects behaviour by comparing HTTPError.Code against these values instead of matching on Message. A dispatcher may add a code within a contract major version, so treat an unknown code as a plain failure of the status it arrived with.
const ( // APIVersion is the dispatcher HTTP contract version this SDK is written // against, as major.minor. It is announced on every request so that a // server implementing an incompatible contract rejects the request // explicitly instead of answering a shape the client cannot read. A server // written before the contract was versioned ignores the header. APIVersion = "1.2" )
const StateExited = "RunStateExited"
StateExited is the terminal state string reported by the dispatcher. An exited debuglet with an empty Error succeeded; a nonempty Error is a workload failure.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Account ¶
type Account struct {
ID string `json:"id"`
Name string `json:"name"`
Role string `json:"role"`
AccountKey string `json:"account_key"`
RecoveryCode string `json:"recovery_code"`
}
Account is one account together with the credentials an issuing operation returned for it. AccountKey and RecoveryCode are shown by the dispatcher exactly once, at the operation that minted them, and cannot be read back. Treat both as secrets: store them with owner-only permissions and keep them out of logs, command output and receipts.
type Client ¶
type Client struct {
// contains filtered or unexported fields
}
Client talks to one dispatcher endpoint. Create it with New.
func New ¶
New validates endpoint and options and returns a Client. The endpoint is an explicit base URL, optionally with a path prefix that is preserved on every route; plaintext HTTP is accepted only for literal loopback IPs.
func (*Client) Cancel ¶
Cancel asks the dispatcher to abort a debuglet on the given executor. A nil error is an acknowledgement, not proof that execution stopped.
func (*Client) Connection ¶
func (c *Client) Connection(ctx context.Context) (ConnectionInfo, error)
Connection reads optional local-executor connection metadata. Older servers may return an HTTPError with status 404; their ordinary HTTP API remains usable.
func (*Client) CreateAccount ¶
CreateAccount registers an account and returns its first credentials. They are returned exactly once: the dispatcher stores only their digests. The caller is responsible for storing them where only its user can read them.
func (*Client) Login ¶
Login exchanges an account key for a session. An empty account key asks a dispatcher that serves the local development profile for a credential for its own local account; every other dispatcher refuses it. The returned Session.Token is what Options.Credential takes.
func (*Client) Logout ¶
Logout revokes the session this client presents. The token is refused from then on, before its own expiry. A client without a credential logs nothing out and reports the dispatcher's authentication failure.
func (*Client) Recover ¶
Recover consumes a recovery code and returns the replacement credentials of the one account that code belongs to. Every session of that account is revoked by the dispatcher first. A recovery code can name no other account, so recovering never grants ownership of somebody else's.
func (*Client) SubmitTEST ¶
func (c *Client) SubmitTEST(ctx context.Context, batch *PreparedBatch) (Submission, error)
SubmitTEST creates a TEST payment intent for the batch and submits it.
func (*Client) Version ¶
func (c *Client) Version(ctx context.Context) (ServerVersion, error)
Version reports the dispatcher's version identities. It is a report, not an ABI negotiation: the request itself carries APIVersion, and a server that cannot serve it rejects the request. A server written before the contract was versioned answers with Version only, leaving the other fields empty.
func (*Client) Whoami ¶
Whoami reports the account this client's credential authenticates as. It is the cheapest way to tell a working credential from an expired or revoked one: the latter answers an *HTTPError with CodeUnauthorized.
func (*Client) WithCredential ¶
WithCredential returns a copy of this client that presents the given session token. The endpoint, transport and timeouts are unchanged, so a credential obtained from one dispatcher cannot be attached to another by accident: a different dispatcher means a different Client.
type ConnectionInfo ¶
type ConnectionInfo struct {
SchemaVersion int `json:"schema_version"`
Mode string `json:"mode"`
GRPCAddress string `json:"grpc_address"`
YamuxAddress string `json:"yamux_address"`
}
ConnectionInfo describes the control listeners announced by a local dispatcher. It does not grant access or infer control addresses from an HTTP URL.
type HTTPError ¶
HTTPError reports a response the client did not accept: any status other than the one expected for the route, including other 2xx codes. Code is the dispatcher's stable failure code, the field to branch on; Message is a bounded, sanitized diagnostic for a human and must not be parsed. A server that sends no documented envelope leaves Code empty. Unrecognized JSON bodies use a generic diagnostic. Recognized auth_key fields and known submission keys are redacted. Path never contains a query or request body.
type LogEntry ¶
type LogEntry struct {
ID int64 `json:"id"`
Timestamp string `json:"timestamp"`
Output []byte `json:"output"`
}
LogEntry is one stored output chunk. Output holds the exact guest bytes; Timestamp is the server's opaque string.
type LogOptions ¶
LogOptions selects a log page. After is a cursor (entry ID) that must be >= 0; Limit zero defaults to 100, otherwise it must be within 1..1000.
type LogPage ¶
type LogPage struct {
State string `json:"state"`
Error string `json:"error"`
After int64 `json:"after"`
Logs []LogEntry `json:"logs"`
HasMore bool `json:"has_more"`
}
LogPage is one page of guest output.
type Node ¶
type Node struct {
ID string `json:"id"`
Ready bool `json:"ready"`
LastSeen int64 `json:"last_seen"`
Version string `json:"version"`
TeslaDelaySec int64 `json:"tesla_delay_sec"`
TeslaAnchorTimestampNs int64 `json:"tesla_anchor_timestamp_ns"`
TeslaAnchorKey []byte `json:"tesla_anchor_key"`
PricePerBw int64 `json:"price_per_bw"`
Currency string `json:"currency"`
}
Node is one executor as reported by GET executors.
type Options ¶
type Options struct {
// HTTPClient supplies transport settings. It is cloned, never mutated,
// and redirects are always rejected. nil uses a fresh client.
HTTPClient *http.Client
// RequestTimeout bounds each request including its body read. Zero
// defaults to 10 s; a negative value is invalid.
RequestTimeout time.Duration
// AllowRemoteTEST permits TEST submissions to endpoints other than a
// literal loopback IP. It is an accident guard, not server authorization:
// an SSH-forwarded loopback endpoint is still an operator-selected remote
// service.
AllowRemoteTEST bool
// Credential is the session token this client presents on every request,
// as an Authorization bearer header. It is obtained from Login and belongs
// to exactly one dispatcher: a Client is bound to one origin and refuses
// redirects, so a credential never travels to another one. It is never
// written to a log, an error message or a returned diagnostic. Empty makes
// unauthenticated requests, which a dispatcher serving the local
// development profile still accepts.
Credential string
}
Options configures a Client. The zero value is valid for a loopback endpoint: a fresh HTTP client, a 10 s per-request timeout and no remote TEST submissions.
type Policy ¶
type Policy struct {
FloorBW int64 `json:"floor_bw"`
CeilBW int64 `json:"ceil_bw"`
TimeoutMS int64 `json:"timeout_ms"`
Addresses []string `json:"addresses"`
RequireICMP bool `json:"require_icmp"`
ListenUDP bool `json:"listen_udp"`
ListenTCP bool `json:"listen_tcp"`
ListenSCION bool `json:"listen_scion"`
}
Policy is the network policy requested for a debuglet.
type PreparedBatch ¶
type PreparedBatch struct {
// contains filtered or unexported fields
}
PreparedBatch is an immutable, validated batch produced by Prepare. The same serialized debuglets array is sent for the payment intent and the submission, so the server's request hash check sees identical values. A zero or nil PreparedBatch is invalid.
func Prepare ¶
func Prepare(requests []Request) (*PreparedBatch, error)
Prepare validates requests and freezes them into one immutable serialized batch used for both submission steps.
type Request ¶
type Request struct {
// OrderID must be unique within one batch.
OrderID int64 `json:"order_id"`
// StartTimestamp is an optional Unix epoch start time.
StartTimestamp *int64 `json:"start_time,omitempty"`
ExecutorID string `json:"executor_id"`
Args []string `json:"args,omitempty"`
// Wasm is the guest binary; it is transmitted base64-encoded by
// encoding/json.
Wasm []byte `json:"wasm"`
Policy Policy `json:"policy"`
}
Request describes one debuglet in a batch. Field order and JSON keys match the dispatcher's request model exactly.
type ServerVersion ¶
type ServerVersion struct {
Version string `json:"version"`
APIVersion string `json:"api_version"`
APIVersions []string `json:"api_versions"`
BinaryVersion string `json:"binary_version"`
BinaryRevision string `json:"binary_revision"`
ProtocolVersion string `json:"protocol_version"`
}
ServerVersion reports a dispatcher's version identities. Version is its configured string, retained from before the HTTP contract was versioned. APIVersion is the HTTP contract the server implements and APIVersions lists the major contract versions it serves; BinaryVersion and BinaryRevision identify the build, and ProtocolVersion is the executor control protocol, which no HTTP client speaks. Every field beyond Version is empty when the server predates contract versioning.
type Session ¶
type Session struct {
Token string `json:"token"`
CSRFToken string `json:"csrf_token"`
ExpiresAt int64 `json:"expires_at"`
ID string `json:"id"`
Name string `json:"name"`
Role string `json:"role"`
}
Session is an issued session. Token is the bearer credential to put in Options.Credential. CSRFToken is only of interest to a browser client that received the session as a cookie; a native client never needs it. ExpiresAt is Unix seconds.
type State ¶
type State struct {
State string `json:"state"`
Error string `json:"error"`
ExecutorID string `json:"executor_id"`
}
State is a debuglet's reported state. Unknown state strings are preserved.
type Submission ¶
Submission is the result of an accepted TEST submission. IDs are in batch order. No auth key is exposed.
type SubmissionError ¶
SubmissionError reports a failed SubmitTEST. Stage is "intent" or "submit". TransactionID is retained when the intent had already been created. OutcomeUnknown is set conservatively when the submission may have been accepted by the server although no valid response was observed (transport or read failure after sending, malformed success, an unexpected submission 2xx, or a server 5xx); it is uncertainty, not proof of acceptance. A validated pre-send failure or a 4xx response is a rejection with OutcomeUnknown false.
func (*SubmissionError) Code ¶
func (e *SubmissionError) Code() string
Code returns the dispatcher's failure code when the submission failed on a response that carried one, and "" otherwise. It never changes how the outcome itself is classified: OutcomeUnknown stays the only statement about whether the submission may have been accepted.
func (*SubmissionError) Error ¶
func (e *SubmissionError) Error() string
func (*SubmissionError) Unwrap ¶
func (e *SubmissionError) Unwrap() error