Documentation
¶
Overview ¶
Package servicecatalog defines Forge's browse-only, declared RPC/code inventory. It contains no endpoint values, credentials, invocation handles or runtime health.
Index ¶
- Constants
- func ForBundle(c *Catalog)
- func Idempotency(level string) string
- func Locate(c *Catalog, readFile func(path string) ([]byte, error))
- func MethodID(scope, owner, method string) string
- func MethodIdentity(scope, owner, namespace, method string) (id, legacyName string)
- func NewClient[T any](binding ClientBinding, ...) T
- type Binding
- type Catalog
- type Client
- type ClientBinding
- type CodeMethod
- type Component
- type Diagnostic
- type Implementation
- type Method
- type Process
- type Serve
- type Service
- type Source
Constants ¶
const ( Schema = "forge.dev/service-catalog/v1" GeneratedPath = "gen/forge_service_catalog.json" BundlePath = "forge/service-catalog.json" )
const DiagnosticBundleMethodSetsOmitted = "bundle_method_sets_omitted"
DiagnosticBundleMethodSetsOmitted marks a catalog whose code method sets (of components, implementation candidates and bindings) were left out: an empty Methods list there means "not recorded", never "has no methods". A bundle copy always carries it (ForBundle strips the sets from a catalog an earlier forge committed), and since v1.0.8 so does the committed gen/ catalog, which records none: a method set is a function of arbitrary Go in its package, so recording it made gen/ stale on Go changes no forge input saw.
Variables ¶
This section is empty.
Functions ¶
func ForBundle ¶ added in v1.0.6
func ForBundle(c *Catalog)
ForBundle reduces c to the copy a bundle carries: what a hosted reader serves to a browser, bounded by what its readers use rather than by the project's size.
- Each service's Descriptor keeps only Schemas, the request/response shapes the RPC explorer renders. Methods, Messages, SchemaFiles, enums and Go package data are the generator's own view, and were most of a large project's catalog.
- The code method sets of components, implementation candidates and bindings are dropped, and the DiagnosticBundleMethodSetsOmitted diagnostic says so (gen/ has carried none since v1.0.8; a catalog an earlier forge committed still does). The topology stays: every component, binding, candidate, provider and client. Method sets are one entry per Go method reachable through the composition graph (reliant: ~3,000 entries, 1.2 MB), and no hosted reader uses them.
- Idempotency is the closed set Method documents (Idempotency).
The result is still schema v1 and decodes with Decode. Sources are left as they are; Locate runs before or after it.
func Idempotency ¶ added in v1.0.6
Idempotency maps a method's protobuf idempotency level (the MethodOptions.IdempotencyLevel name, or "" when unset) to the catalog's closed set: IDEMPOTENT, NO_SIDE_EFFECTS, else UNKNOWN.
func Locate ¶ added in v1.0.6
Locate turns every committed Source in c into a located one: it resolves each Symbol to its line in the source being built, which is what a bundle carries. readFile reads a module-relative path (Decode has already refused absolute and escaping ones). Each file is parsed once, syntax only.
A source whose file cannot be read or parsed, or no longer declares its symbol, becomes the zero Source: the location is unknown, never guessed. Sources that are already located or unknown are left alone.
func MethodID ¶
MethodID is a stable low-cardinality symbol identity. Signature, source line, build, instance and arguments deliberately do not enter the identity.
func MethodIdentity ¶
MethodIdentity is the join metadata shared by the catalog and generated decorators. Owner is the exposed interface/receiver whose method set is being decorated, NOT the receiver declaring an inherited/embedded method. Namespace is the actual instrumentation namespace (normally the Go package clause), not an import-path basename. Neither signature nor declaration location enters ID.
func NewClient ¶
func NewClient[T any](binding ClientBinding, constructor func(connect.HTTPClient, string, ...connect.ClientOption) T, httpClient connect.HTTPClient, baseURL string, opts ...connect.ClientOption) T
NewClient calls the original generated Connect constructor without changing its HTTPClient, resolved baseURL or option order. T remains its generated client interface. Declare this call directly in a composition provider so forge generate can inventory it. Dynamic metadata is explicitly unresolved.
Types ¶
type Binding ¶
type Binding struct {
Consumer string `json:"consumer"`
Field string `json:"field"`
Interface string `json:"interface"`
Methods []CodeMethod `json:"methods"`
Candidates []string `json:"candidates"` // assignable producers, NOT selected bindings
Providers []string `json:"providers"` // accessors in this field's composition expression
Resolution string `json:"resolution"` // composition_expression or unresolved
}
type Catalog ¶
type Catalog struct {
Schema string `json:"schema"`
Module string `json:"module"`
Processes []Process `json:"processes"`
Services []Service `json:"services"`
Components []Component `json:"components"`
Bindings []Binding `json:"bindings"`
Clients []Client `json:"clients"`
Diagnostics []Diagnostic `json:"diagnostics"`
}
Catalog is generated from the same typed composition model and wire descriptor as the application. Missing evidence is explicit; none of these edges proves a call.
func Decode ¶
Decode validates catalog bytes before a browser/hosted ingest consumes them. It has no size bound of its own: a catalog grows with the project it describes, and the bytes are already in memory, so the bound belongs to the reader that fetched them (a bundle layer's total, a registry blob read). It authenticates no provenance: callers must verify the containing OCI bundle digest and apply their existing project/environment authorization.
It accepts either Source form: the committed one (path + symbol) and the located one a bundle carries (path + line). DecodeLocated accepts only the latter.
func DecodeLocated ¶ added in v1.0.6
DecodeLocated is Decode for a bundle's copy: every source must be located (path + line) or unknown, never symbolic. A bundle's readers decode the v1 Source as {path, line} and refuse any other key, so a symbolic source that reached one would void the whole catalog.
type Client ¶
type Client struct {
ID string `json:"id"`
Provider string `json:"provider"`
Service string `json:"service"`
ConfigField string `json:"config_field"` // existing fully-qualified proto config field, NOT its value
Constructor string `json:"constructor"`
Source Source `json:"source"`
Resolution string `json:"resolution"` // declared; no target URL inference
}
type ClientBinding ¶
ClientBinding describes the existing endpoint's config FIELD, not its value. Service is a fully-qualified protobuf service (use the generated service name constant); ConfigField is e.g. "shop.config.v1.API.orders_url". This metadata grants no authority and changes no HTTP, auth, tracing or retry behavior.
type CodeMethod ¶
type CodeMethod struct {
ID string `json:"id"`
Name string `json:"name"`
Signature string `json:"signature"` // Go types qualified by import path
Scope string `json:"scope"` // legacy instrumentation scope
LegacyName string `json:"legacy_name"` // legacy pkg.Method span name
Source Source `json:"source"`
}
type Component ¶
type Component struct {
ID string `json:"id"`
Name string `json:"name"`
Kind string `json:"kind"`
Type string `json:"type"`
Source Source `json:"source"`
Methods []CodeMethod `json:"methods"`
// ImplementationCandidates are assignable concrete types in the component's
// package. They are not proof of which implementation a constructor returns.
ImplementationCandidates []Implementation `json:"implementation_candidates"`
}
type Diagnostic ¶
type Implementation ¶
type Implementation struct {
Type string `json:"type"`
Source Source `json:"source"`
Methods []CodeMethod `json:"methods"`
}
type Method ¶
type Method struct {
ID string `json:"id"` // full proto service + "/" + method
Name string `json:"name"`
Input string `json:"input"`
Output string `json:"output"`
ClientStreaming bool `json:"client_streaming"`
ServerStreaming bool `json:"server_streaming"`
Idempotency string `json:"idempotency"` // UNKNOWN, IDEMPOTENT, NO_SIDE_EFFECTS
AuthRequired bool `json:"auth_required"`
}
type Serve ¶
type Serve struct {
Component string `json:"component"` // handler component; method names join to Component.Methods
Service string `json:"service"` // fully-qualified protobuf service
RouteSet string `json:"route_set"`
Audience string `json:"audience"`
Resolution string `json:"resolution"` // declared_route_set; not runtime observation
}
type Service ¶
type Service struct {
Name string `json:"name"`
ProtoFile string `json:"proto_file"`
Methods []Method `json:"methods"`
// Descriptor is the existing forge descriptor (gen/forge_descriptor/) ServiceDef, unchanged:
// Schemas, SchemaFiles, Enums and field validate/validate_options are the
// authoritative schema graph. Do not invent a second validation dialect.
Descriptor json.RawMessage `json:"descriptor"`
}
type Source ¶
type Source struct {
Path string `json:"path"` // module-relative, never absolute
// Symbol is the declaration's name in Path: "NewOrders" (a func), "Orders"
// (a type), or "Orders.Get" (a method, or a method of an interface type).
// Only the committed form carries it.
Symbol string `json:"symbol,omitempty"`
Line int `json:"line"`
}
Source locates a declaration, in one of two forms.
The committed gen/ catalog names it: Path plus Symbol, and no line. A line number moves whenever unrelated code above it does, so a committed catalog that recorded one went stale on every merge that touched a handler file.
The bundle copy carries Path plus Line: Locate resolves each Symbol against the source being built, and the bundle's readers have always required a line with a path. The zero Source means the location is unknown.
func (Source) MarshalJSON ¶ added in v1.0.6
MarshalJSON writes the committed form ({path, symbol}) when s is symbolic, and the located form ({path, line}) otherwise.