Documentation
¶
Overview ¶
Package remote implements the versioned online Starmap-to-Starmap generation protocol and its verified client.
Index ¶
- Constants
- func DefaultTransferClient() *http.Client
- func GenerationManifestPath(generationID string) string
- func ManifestETag(generationID string) string
- func MarshalManifest(manifest catalogs.GenerationManifest) ([]byte, error)
- func MarshalSourceChain(chain SourceChain) ([]byte, error)
- func NewTransferClient(policy TransferPolicy) (*http.Client, error)
- func NewTransport(policy TransferPolicy) (*http.Transport, error)
- func PayloadPath(generationID string) string
- func RetryBoundary(header http.Header, now time.Time) (time.Time, bool)
- type Client
- func (c *Client) FetchCurrent(ctx context.Context) (catalogs.Generation, error)
- func (c *Client) FetchCurrentIfChanged(ctx context.Context, generationID string) (generation catalogs.Generation, changed bool, err error)
- func (c *Client) FetchGeneration(ctx context.Context, generationID string) (catalogs.Generation, error)
- func (c *Client) FetchSourceChain(ctx context.Context) (SourceChain, error)
- func (c *Client) OpenEventStream(ctx context.Context, lastEventID string) (*EventStream, error)
- type EventStream
- type ProgressFunc
- type Publication
- type RefusalError
- type Reply
- type SourceChain
- type SourceChainHop
- type StreamEvent
- type Transfer
- type TransferPolicy
- type TransferProgress
- type TransferStage
Constants ¶
const ( // SourceChainPath returns the source-chain manifest of the serving node. SourceChainPath = CatalogPath + "/source-chain" // SourceChainMediaType identifies strict source-chain JSON. SourceChainMediaType = "application/vnd.agentstation.starmap.source-chain+json" // SourceChainSchemaVersion is the current source-chain document version. SourceChainSchemaVersion uint64 = 1 // MaxSourceChainHops bounds the hops one document may disclose. A chain // discloses topology, so the bound keeps the disclosure small and keeps a // forged document from growing without limit. MaxSourceChainHops = 16 )
const ( // SourceChainHealthUnknown means the node reported no grade yet. SourceChainHealthUnknown = "unknown" // SourceChainHealthOK means the node reached its last objective. SourceChainHealthOK = "ok" // SourceChainHealthDegraded means the node works with reduced evidence. SourceChainHealthDegraded = "degraded" SourceChainHealthUnavailable = "unavailable" )
Source-chain health codes. The set stays closed, so a document discloses a grade and never free-form text.
const ( // CatalogPath is the current catalog resource path. CatalogPath = "/catalog" // ManifestPath returns the current strict generation manifest. ManifestPath = CatalogPath + "/manifest" // GenerationsPath prefixes immutable generation resource routes. GenerationsPath = CatalogPath + "/generations" // EventStreamPath returns post-commit catalog publication hints over SSE. EventStreamPath = "/updates/stream" // CatalogPublishedEvent is the sole catalog publication event name. CatalogPublishedEvent = "catalog.published" // ManifestMediaType identifies strict generation-manifest JSON. ManifestMediaType = "application/vnd.agentstation.starmap.catalog-manifest+json" )
const ( // DefaultConnectTimeout bounds one TCP connection attempt. DefaultConnectTimeout = 30 * time.Second // DefaultTLSHandshakeTimeout bounds one TLS handshake. DefaultTLSHandshakeTimeout = 30 * time.Second // DefaultResponseHeaderTimeout bounds the wait for response headers after // the client writes the request. DefaultResponseHeaderTimeout = 60 * time.Second // DefaultTransferIdleTimeout bounds the time a transfer may make no // progress. Every successful body read resets the timer. DefaultTransferIdleTimeout = 2 * time.Minute // DefaultTransferMaxDuration bounds one complete body transfer. A 64 MiB // body at 256 kilobits per second takes about 35 minutes, so this value // leaves headroom over a slow link. DefaultTransferMaxDuration = 60 * time.Minute // DefaultMaxCompressedBytes bounds the bytes read from one response body. DefaultMaxCompressedBytes int64 = 64 << 20 )
Transfer bounds. Each value bounds one stage of one finite HTTP body transfer, for a catalog download and for an ordinary provider request alike. No value bounds a subscription lifetime.
const (
// EventStreamMediaType identifies the catalog publication SSE stream.
EventStreamMediaType = "text/event-stream"
)
Variables ¶
This section is empty.
Functions ¶
func DefaultTransferClient ¶ added in v0.16.0
DefaultTransferClient returns a transfer client with the default policy. The default policy is a set of constants, so this call cannot fail.
func GenerationManifestPath ¶
GenerationManifestPath returns the immutable manifest route for generationID.
func ManifestETag ¶
ManifestETag returns the strong entity tag for a generation manifest. A generation ID is immutable and restricted to HTTP entity-tag-safe bytes.
func MarshalManifest ¶
func MarshalManifest(manifest catalogs.GenerationManifest) ([]byte, error)
MarshalManifest returns strict JSON bytes for the server route.
func MarshalSourceChain ¶ added in v0.16.0
func MarshalSourceChain(chain SourceChain) ([]byte, error)
MarshalSourceChain returns strict JSON bytes for the server route.
func NewTransferClient ¶ added in v0.16.0
func NewTransferClient(policy TransferPolicy) (*http.Client, error)
NewTransferClient returns an HTTP client that applies the policy through its transport. The client sets no total timeout, because http.Client.Timeout also covers body reads and cannot coexist with progress-aware transfers.
func NewTransport ¶ added in v0.16.0
func NewTransport(policy TransferPolicy) (*http.Transport, error)
NewTransport returns an HTTP transport that applies the connection, TLS, and response-header bounds of the policy. The body bounds belong to Transfer.
func PayloadPath ¶
PayloadPath returns the immutable canonical payload route for generationID.
Types ¶
type Client ¶
type Client struct {
// contains filtered or unexported fields
}
Client fetches one exact current generation from a versioned Starmap API.
func NewClient ¶
NewClient creates a remote generation client. baseURL is the trusted, versioned HTTPS API root, for example https://starmap.example.com/api/v1. NewClient accepts plain HTTP only on loopback. The supplied HTTP client may add authentication or stricter TLS policy, but HTTPS responses must retain a standard verified certificate chain.
func (*Client) FetchCurrent ¶
FetchCurrent fetches the current manifest followed by its immutable, generation-addressed payload and validates their binding and compatibility.
func (*Client) FetchCurrentIfChanged ¶
func (c *Client) FetchCurrentIfChanged( ctx context.Context, generationID string, ) (generation catalogs.Generation, changed bool, err error)
FetchCurrentIfChanged conditionally fetches the current manifest relative to generationID. It returns changed=false without fetching a payload when the publisher reports that generationID is still current.
func (*Client) FetchGeneration ¶
func (c *Client) FetchGeneration(ctx context.Context, generationID string) (catalogs.Generation, error)
FetchGeneration fetches and verifies one immutable generation by ID.
func (*Client) FetchSourceChain ¶ added in v0.16.0
func (c *Client) FetchSourceChain(ctx context.Context) (SourceChain, error)
FetchSourceChain returns the source-chain manifest of the configured publisher. A publisher that serves no chain answers with a not-found status, so a caller treats that upstream as an origin without a disclosed chain.
func (*Client) OpenEventStream ¶
OpenEventStream opens the publication stream. A nonempty lastEventID becomes the standard Last-Event-ID request header.
type EventStream ¶
type EventStream struct {
// contains filtered or unexported fields
}
EventStream is one caller-owned catalog publication stream.
func (*EventStream) Close ¶
func (s *EventStream) Close() error
Close closes the underlying response body and unblocks Next.
func (*EventStream) Next ¶
func (s *EventStream) Next() (StreamEvent, error)
Next returns the next complete publication or comment activity frame.
type ProgressFunc ¶ added in v0.16.0
type ProgressFunc func(TransferProgress)
ProgressFunc receives one transfer progress report. Implementations must return promptly, because the transfer calls them inline.
type Publication ¶
type Publication struct {
GenerationID string `json:"generation_id"`
Sequence uint64 `json:"sequence"`
}
Publication identifies one committed immutable catalog generation.
type RefusalError ¶ added in v0.16.0
type RefusalError struct {
// StatusCode is the refusal status, such as 429 or 503.
StatusCode int
// Resource is the safe label of the refused resource. It names no URL.
Resource string
// NotBefore is the earliest time the publisher accepts another request.
NotBefore time.Time
// Err is the underlying transport or status error.
Err error
}
RefusalError reports that the publisher refused a request and named the earliest time a client may try again. The boundary is a hard floor. A client waits for it instead of its own backoff. The client also adds jitter, so a fleet does not return at one instant.
func (*RefusalError) Error ¶ added in v0.16.0
func (e *RefusalError) Error() string
Error returns the safe refusal text. It names the resource and the status, never the endpoint.
func (*RefusalError) Unwrap ¶ added in v0.16.0
func (e *RefusalError) Unwrap() error
Unwrap returns the underlying error.
type Reply ¶ added in v0.16.0
type Reply struct {
// StatusCode is the reply status.
StatusCode int
// Header is a caller-owned copy of the reply header.
Header http.Header
// Body is the complete reply body.
Body []byte
}
Reply is one complete bounded HTTP reply. The transfer already read and closed the body, so a caller owns no stream and closes nothing.
type SourceChain ¶ added in v0.16.0
type SourceChain struct {
// SchemaVersion is the document version. A reader rejects another version.
SchemaVersion uint64 `json:"schema_version"`
// Identity is the safe identity of the serving node.
Identity string `json:"identity"`
// Health is what the serving node observed while it read its own source.
Health string `json:"health"`
// UpstreamHealth is the health the serving node's upstream reported about
// itself. It stays independent of Health.
UpstreamHealth string `json:"upstream_health"`
// SourceIdentity is the safe identity of the source the node reads.
SourceIdentity string `json:"source_identity,omitempty"`
// GenerationID identifies the catalog generation the node serves.
GenerationID string `json:"generation_id,omitempty"`
// ChannelUpdatedAt is the propagated time the origin channel last moved.
// Every hop passes the value through unchanged, so a downstream grades the
// whole chain instead of its own last check.
ChannelUpdatedAt time.Time `json:"channel_updated_at"`
// ObservedAt is when the serving node built the document.
ObservedAt time.Time `json:"observed_at"`
// Hops lists the upstream nodes, nearest hop first.
Hops []SourceChainHop `json:"hops,omitempty"`
}
SourceChain is what one Starmap discloses about itself and the hops above it. The serving node is Identity, and Hops lists its upstream nodes with the nearest hop first. A downstream reads the document to reject a cycle and to evaluate the propagated channel freshness of the whole chain.
func UnmarshalSourceChain ¶ added in v0.16.0
func UnmarshalSourceChain(data []byte) (SourceChain, error)
UnmarshalSourceChain decodes and validates one source-chain document.
func (SourceChain) Identities ¶ added in v0.16.0
func (c SourceChain) Identities() []string
Identities returns the serving identity followed by every hop identity, in chain order. A caller uses the list to reject a self reference and a cycle.
func (SourceChain) Validate ¶ added in v0.16.0
func (c SourceChain) Validate() error
Validate reports whether the document is a usable source chain. It bounds the hop count and every identity, and it accepts only the closed health set.
type SourceChainHop ¶ added in v0.16.0
type SourceChainHop struct {
Identity string `json:"identity"`
Health string `json:"health"`
PublishedAt time.Time `json:"published_at,omitempty"`
ObservedAt time.Time `json:"observed_at,omitempty"`
}
SourceChainHop is one sanitized upstream node of a served chain. A hop names a safe identity and a grade. It never names an address, a host, or a token.
type StreamEvent ¶
type StreamEvent struct {
Publication *Publication
Comment string
EventID string
}
StreamEvent is one parsed SSE publication or comment activity frame. Comments establish transport activity but never contain publication data.
type Transfer ¶ added in v0.16.0
type Transfer struct {
// Client sends the request. A nil client uses the default transfer client.
Client *http.Client
// Policy bounds the transfer. A zero policy uses the defaults.
Policy TransferPolicy
// Progress receives progress reports. A nil value reports nothing.
Progress ProgressFunc
}
Transfer reads one HTTP body under a bound and reports its progress.
func (Transfer) Body ¶ added in v0.16.0
Body sends request and reads the complete response body under the policy. The resource is a safe label for progress and error reporting.
Body returns a *errors.TimeoutError when the inactivity bound or the per-transfer maximum stops the transfer, and a *errors.ValidationError when the body exceeds the size bound.
func (Transfer) Response ¶ added in v0.16.0
func (t Transfer) Response( ctx context.Context, request *http.Request, resource string, ) (*http.Response, error)
Response sends request under the same bounds as Body and returns the reply as an *http.Response whose body already sits in memory. A later read of that body cannot stall. A caller that hands the reply to an existing decoder therefore keeps the inactivity bound and the per-transfer maximum. The caller still closes the body, and that close does nothing.
Response reports the same error types as Body.
type TransferPolicy ¶ added in v0.16.0
type TransferPolicy struct {
// ConnectTimeout bounds one TCP connection attempt.
ConnectTimeout time.Duration
// TLSHandshakeTimeout bounds one TLS handshake.
TLSHandshakeTimeout time.Duration
// ResponseHeaderTimeout bounds the wait for response headers.
ResponseHeaderTimeout time.Duration
// IdleTimeout bounds the time one transfer may make no progress.
IdleTimeout time.Duration
// MaxDuration bounds one complete body transfer. Zero is invalid.
MaxDuration time.Duration
// MaxCompressedBytes bounds the bytes read from one response body.
MaxCompressedBytes int64
}
TransferPolicy bounds one finite HTTP body transfer at every stage. It replaces http.Client.Timeout, which also covers body reads and therefore rejects a healthy slow link.
func DefaultTransferPolicy ¶ added in v0.16.0
func DefaultTransferPolicy() TransferPolicy
DefaultTransferPolicy returns the shared transfer bounds.
func (TransferPolicy) Validate ¶ added in v0.16.0
func (p TransferPolicy) Validate() error
Validate reports whether every bound is positive. A zero maximum duration is invalid, because an unbounded transfer can hold a connection forever.
type TransferProgress ¶ added in v0.16.0
type TransferProgress struct {
// Resource is the safe label of the transferred resource.
Resource string
// Stage is the phase that produced this report.
Stage TransferStage
// BytesReceived is the running count of body bytes read.
BytesReceived int64
// TotalBytes is the declared body length, or zero when the response
// declares none.
TotalBytes int64
}
TransferProgress reports how much of one transfer arrived. The resource is a safe caller-supplied label. It never carries a URL, a token, or a host name.
type TransferStage ¶ added in v0.16.0
type TransferStage string
TransferStage names one phase of one catalog transfer.
const ( // TransferStageHeaders reports that the response headers arrived. TransferStageHeaders TransferStage = "headers" // TransferStageBody reports body bytes in flight. TransferStageBody TransferStage = "body" // TransferStageComplete reports a finished body. TransferStageComplete TransferStage = "complete" )