Documentation
¶
Overview ¶
Package bundle loads and validates the read-only descriptor bundle (descriptors.binpb + openapi.json + versions.yaml) at boot, fail-fast. The route → message binding is read verbatim (zero inference); every binding is resolved against the FileDescriptorSet here so the runtime never has to. Transform stanzas live in the operator-owned resolution.yaml at the bundle root; the per-version layer manifests are binding-only. Unknown keys are refused by strict decode.
Index ¶
- type Bundle
- func (b *Bundle) Contract(version string) (*Contract, bool)
- func (b *Bundle) Lookup(path, method, version string) (*Contract, bool)
- func (b *Bundle) LookupRoute(path, method string) (*Contract, bool)
- func (b *Bundle) Message(fullName string) (protoreflect.MessageDescriptor, error)
- func (b *Bundle) Versions() []string
- type Contract
- func (c *Contract) Chain() []*Contract
- func (c *Contract) ContractVersion() string
- func (c *Contract) ErrorMessage(status int) (string, bool)
- func (c *Contract) ErrorResponseOps(status int) []transform.Op
- func (c *Contract) Method() string
- func (c *Contract) RequestMessage() string
- func (c *Contract) RequestOps() []transform.Op
- func (c *Contract) ResponseMessage() string
- func (c *Contract) ResponseOps() []transform.Op
- func (c *Contract) Route() string
- func (c *Contract) Strict() bool
- func (c *Contract) Target() string
- func (c *Contract) TransformTarget() string
- type MessageNotFoundError
- type PackageCollisionError
- type ParseError
- type ReadError
- type UnsupportedVersionError
- type ValidationError
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Bundle ¶
type Bundle struct {
// contains filtered or unexported fields
}
Bundle holds the resolved view of a loaded bundle directory. Internally a flat list of contracts: a layer holds one or more contracts sharing a contract_version and distinguished by (route, method). The list preserves the load order (sorted-layer × layer's versions.yaml order) so iteration is deterministic, and the byVersion index gives O(1) per-version lookups that LookupRoute, Versions, and resolveChains all rely on.
func Load ¶
Load reads, parses, validates, and resolves the bundle in dir. The bundle is a directory of layer subdirectories, each holding descriptors.binpb, openapi.json, and versions.yaml. Any failure is fatal (a typed error); the caller refuses to start.
func (*Bundle) Contract ¶
Contract returns the first contract in the bundle whose contract_version is version. A single-route layer has one contract per version, so this is unambiguous. A multi-route layer has many contracts per version (one per route); Contract returns the first by load order — callers that need a specific (version, route, method) binding use LookupRoute first.
func (*Bundle) Lookup ¶ added in v0.5.0
Lookup returns the contract that matches (path, method, version) — the full resolution key used by the proxy once the inbound contract-version header has been read. It is the only correct dispatch for a multi-route bundle: Contract(version) would return whichever contract for that version happens to be first in load order, hiding the per-route binding.
On miss, ok is false. Misses come in three flavours, all collapsed into the same (nil, false) result here; the caller (negotiate.Resolve) maps them onto the right wire-error:
- version is absent from the bundle,
- version is present but does not bind this (path, method),
- path/method is unknown to every version (this case is normally handled before negotiate by the proxy's route gate using LookupRoute).
For a single-route bundle every version has exactly one contract, so Lookup(c.Route(), c.Method(), c.ContractVersion()) trivially returns c — the degenerate case continues to work without special-casing.
func (*Bundle) LookupRoute ¶ added in v0.5.0
LookupRoute returns the first contract in the bundle that binds (path, method), if any. It is a (value, ok) lookup — idiomatic in the shape of `os.LookupEnv` or `(*sync.Map).Load` — so callers can both gate on membership and use the matched contract without a second pass.
The proxy uses this as the first-pass routing gate: a request whose (URL.Path, Method) is not in the bundle's route set is refused before any other request work (decode, negotiate, upstream call). A wrong-method request — same path, different method — is NOT routed: each contract names exactly one method, so wrong-method folds into the same "no contract binds this" miss that an entirely unknown path produces. The caller emits `unknown_route` 404 in both cases.
Multiple contracts may legally bind the same (route, method) across different `contract_version` values. LookupRoute returns the first match in bundle order; selecting between same-(route, method) contracts is the version-negotiation layer's job — see Lookup for the keyed (path, method, version) form callers reach for once a version is in hand.
func (*Bundle) Message ¶
func (b *Bundle) Message(fullName string) (protoreflect.MessageDescriptor, error)
Message resolves a fully-qualified proto message name against the bundle's FileDescriptorSet.
type Contract ¶
type Contract struct {
// contains filtered or unexported fields
}
Contract is one resolved binding. Fields are unexported with accessors so it satisfies an adapter Binding interface (RequestMessage/ResponseMessage) structurally, with no import cycle.
func (*Contract) ContractVersion ¶
func (*Contract) ErrorMessage ¶ added in v0.7.0
ErrorMessage returns the proto message name the contract binds for an upstream status, if declared. A declared (route, status) is a first-class typed contract response; an undeclared one falls to the aid envelope (or a hard 502 under strict).
func (*Contract) ErrorResponseOps ¶ added in v0.7.0
ErrorResponseOps returns the response transform ops scoped to a declared error status, or nil if none are configured. A nil slice is a byte-identical passthrough in transform.ApplyResponse, so callers can apply it unconditionally.
func (*Contract) RequestMessage ¶
func (*Contract) RequestOps ¶ added in v0.2.0
func (*Contract) ResponseMessage ¶
func (*Contract) ResponseOps ¶ added in v0.2.0
func (*Contract) Strict ¶ added in v0.7.0
Strict reports whether undeclared upstream statuses collapse to a hard 502 for this contract rather than the graceful aid envelope.
func (*Contract) TransformTarget ¶ added in v0.3.0
type MessageNotFoundError ¶
func (*MessageNotFoundError) Error ¶
func (e *MessageNotFoundError) Error() string
type PackageCollisionError ¶ added in v0.5.0
PackageCollisionError is raised at boot when two or more version layers each uniquely contribute proto files into the same proto package. The runtime resolves messages by their fully-qualified name against one merged FileDescriptorSet, so a package owned by multiple layers would have undefined resolution. The disjoint-package guarantee is normally upheld by the wavefront.gen.v<version> namespacing convention; this typed error is the defense-in-depth check that fails fast at boot if the convention is ever violated. Layers is sorted lexically for deterministic messages.
When more than one package collides, Load reports only the lexically-first colliding package — the operator fixes one at a time and re-runs, surfacing the next collision on the next boot.
func (*PackageCollisionError) Error ¶ added in v0.5.0
func (e *PackageCollisionError) Error() string
type ParseError ¶
func (*ParseError) Error ¶
func (e *ParseError) Error() string
func (*ParseError) Unwrap ¶
func (e *ParseError) Unwrap() error
type UnsupportedVersionError ¶
type UnsupportedVersionError struct{ Version int }
func (*UnsupportedVersionError) Error ¶
func (e *UnsupportedVersionError) Error() string
type ValidationError ¶
func (*ValidationError) Error ¶
func (e *ValidationError) Error() string