workerclient

package
v0.1.0 Latest Latest
Warning

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

Go to latest
Published: Jul 23, 2026 License: Apache-2.0 Imports: 27 Imported by: 0

Documentation

Overview

Package workerclient implements the human TUI side of the private worker WS.

FROZEN (docs/11-human-side.md M0): bug fixes only. This legacy dialect is deleted with the TUI once the web door reaches TUI door coverage; the public replacement is llm/workerws.Client under the workerkit domain layer.

Index

Constants

This section is empty.

Variables

View Source
var (

	// ErrWorkerAuthentication is returned when the gateway has conclusively
	// rejected the worker credential. Retrying the same credential cannot heal
	// a 401/403/407, so both initial dial and reconnect treat it as terminal.
	ErrWorkerAuthentication = errors.New("gateway rejected worker credentials")
	// ErrWorkerHandshake is returned for a conclusive non-retryable HTTP or
	// WebSocket handshake response (for example a wrong 404 endpoint).
	ErrWorkerHandshake = errors.New("gateway permanently rejected worker handshake")
	// ErrWorkerAlreadyConnected means another Human worker process currently
	// owns the same authenticated subject. The incumbent is never displaced;
	// this client waits with bounded backoff so it can recover automatically
	// when the incumbent was merely a half-open connection.
	ErrWorkerAlreadyConnected = errors.New("worker token is already active in another Human worker")
	// ErrWorkerOwnershipViolation is terminal for this Client instance. The
	// authenticated worker tried to publish to another worker's completion;
	// retrying the same durable outbox head cannot change that authorization
	// decision and would only flap the connection.
	ErrWorkerOwnershipViolation = errors.New("worker event targets another worker's completion")
	// ErrAssignmentWorkerMismatch means an assignment is leased to a different
	// authenticated worker subject. Reject it before touching the durable outbox:
	// assignment JSON is not an authority source and must never cross subjects.
	ErrAssignmentWorkerMismatch = errors.New("assignment lease owner does not match authenticated worker")
	// ErrEventNotStored marks a deterministic failure which occurred before the
	// exact event could enter the durable outbox. Errors without this marker are
	// commit-ambiguous and callers must retry the same event ID instead of
	// restoring its source draft as though delivery were impossible.
	ErrEventNotStored = errors.New("worker event was definitely not stored")
)
View Source
var (

	// ErrEventQuarantined reports that an event ID belongs to a corrupt durable
	// record which was isolated from delivery. The raw record remains available
	// for operator inspection and the ID must not be reused implicitly.
	ErrEventQuarantined = errors.New("worker event is quarantined after durable outbox corruption")
	// ErrEventPreviouslyRejected reports that an exact event is already in the
	// confirmed rejection tombstone, rather than the send outbox.
	ErrEventPreviouslyRejected = errors.New("worker event was already rejected")
	// ErrEventRejectionPending reports that the exact rejected event remains in
	// the durable inbox and will be offered through Client.Messages.
	ErrEventRejectionPending = errors.New("worker event rejection is pending local recovery")
)
View Source
var ErrWorkerIdentityUnavailable = errors.New("worker identity is not established")

ErrWorkerIdentityUnavailable means the client has not completed a worker hello yet. A durable local intent must wait and retry instead of being converted back into an unsent draft merely because startup began offline.

Functions

func GatewayIdentity

func GatewayIdentity(endpoint, logicalScope string) (string, error)

GatewayIdentity returns the token-free correctness identity shared by the worker outbox and TUI state. A logical scope is appropriate for an embedded gateway whose listener changes; otherwise the canonical worker endpoint is used. Callers must never reuse a logical scope for another gateway database.

func RebindOutboxIdentity

func RebindOutboxIdentity(ctx context.Context, path, oldGatewayID, newGatewayID, workerID string) error

RebindOutboxIdentity validates and rewrites one offline outbox restored into a different logical gateway location. It acquires the normal owner lock and rejects mixed-identity archives; callers should invoke it on staging files before atomically replacing live data.

Types

type Client

type Client struct {
	// contains filtered or unexported fields
}

func Dial

func Dial(ctx context.Context, url, token string) (*Client, error)

Dial uses the private default outbox. Call DialWithOutbox when embedding the client or when the path comes from explicit configuration.

func DialWithOutbox

func DialWithOutbox(ctx context.Context, url, token, outboxPath string) (*Client, error)

DialWithOutbox binds a worker to a durable event outbox and starts its connection lifecycle. A transient initial failure (including connection refused, timeout, 429, or 5xx) returns a live Client which reconnects in the background; a malformed endpoint or conclusive handshake/authentication rejection returns an error immediately. The bearer token is never stored or used as durable identity. After the authenticated gateway hello, pending events are selected by canonical endpoint plus stable worker subject, so a credential rotation for that subject continues the same outbox while another subject cannot replay it.

func DialWithOutboxScope

func DialWithOutboxScope(ctx context.Context, url, token, outboxPath, scope string) (*Client, error)

DialWithOutboxScope is DialWithOutbox with an explicit stable logical gateway identity. It is intended for embedded gateways whose loopback port may change across restarts while the durable gateway database remains the same. The scope is hashed into the outbox namespace and must never be reused for a different gateway correctness domain.

func (*Client) Close

func (client *Client) Close() error

func (*Client) ConfirmRejectedEvent

func (client *Client) ConfirmRejectedEvent(ctx context.Context, eventID string) error

ConfirmRejectedEvent atomically replaces one durable inbox record with a payload-free digest tombstone. Until this explicit acknowledgement succeeds, the client may replay the rejection after process restart or reconnection; afterwards, a duplicate server rejection cannot recreate it.

func (*Client) Messages

func (client *Client) Messages() <-chan Message

func (*Client) SendEvent

func (client *Client) SendEvent(ctx context.Context, assignment completion.Assignment, event completion.Event) error

SendEvent returns success once the exact event is committed to the local send outbox. Network delivery and ACK may happen later. An exact ID already resolved as rejected returns ErrEventPreviouslyRejected instead of a false success, because it will not be sent again.

func (*Client) WorkerID

func (client *Client) WorkerID() string

func (*Client) WorkerIdentity

func (client *Client) WorkerIdentity() (Identity, bool)

WorkerIdentity reports the authenticated identity only after Hello has bound the durable outbox. It is useful to embedders which construct a TUI after an unusually fast handshake; ordinary startup also receives IdentityReady.

type Identity

type Identity struct {
	GatewayID string
	WorkerID  string
}

Identity is established only by the gateway's authenticated Hello. GatewayID is the canonical endpoint (or the caller-supplied logical gateway scope), and WorkerID is the authenticated principal subject. Neither contains a token.

type Message

type Message struct {
	IdentityReady      *Identity
	Assignment         *completion.Assignment
	EventRejected      *workerproto.EventRejected
	RejectedEvent      *completion.Event
	RejectedAssignment *completion.Assignment
	RejectedTaskID     string
	OutboxQuarantine   *OutboxQuarantine
	ConnectionRestored bool
	Err                error
}

type OutboxQuarantine

type OutboxQuarantine struct {
	Count    int
	EventIDs []string
	Path     string
}

OutboxQuarantine is a payload-free operator notice. Corrupt raw rows are retained in worker_outbox_quarantine, while healthy rows continue to send. EventIDs is deliberately bounded and contains only durable opaque IDs.

Jump to

Keyboard shortcuts

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