Documentation
¶
Overview ¶
Package graphql provides the platform's GraphQL connection kind: a toolkit that reaches a GraphQL endpoint through the platform's auth, persona, audit and export pipeline, the way pkg/toolkits/apigateway reaches an OpenAPI-described REST API and pkg/toolkits/gateway reaches an upstream MCP server.
A GraphQL endpoint is one URL that everything is POSTed to, which is why it is a kind of its own rather than a shape of API connection: there is no route to authorize, no path to rank, and a failure is an errors array inside an HTTP 200. What the kind adds on top of the shared upstream transport is a schema it keeps by introspection, an index of the operations that schema exposes, validation of the document a model wrote before it is sent, and an operation-level policy that reduces a document to the fields it selects.
The toolkit registers three tools however many connections it holds: graphql_discover finds an operation and renders a document that runs it, graphql_query executes one, and graphql_export streams one into an asset.
Index ¶
- Constants
- Variables
- type Authenticator
- type Config
- type DiscoverInput
- type DiscoverOutput
- type Error
- type ErrorLocation
- type ExportAsset
- type ExportAssetRef
- type ExportAssetStore
- type ExportConfig
- type ExportDeps
- type ExportProvenance
- type ExportProvenanceCall
- type ExportS3Client
- type ExportShareCreator
- type ExportUserContext
- type ExportVersion
- type ExportVersionStore
- type MultiConfig
- type OAuth2Config
- type OAuthKindHandler
- type OperationDetail
- type OperationSummary
- type PaginateInput
- type PaginationReport
- type QueryInput
- type QueryOutput
- type RankedConnectionOperation
- type RankedOperation
- type RankingMode
- type RoutePolicy
- type SchemaInfo
- type SchemaStore
- type SignedJWTConfig
- type StoredSchema
- type Toolkit
- func (t *Toolkit) AddConnection(name string, config map[string]any) error
- func (t *Toolkit) Close() error
- func (t *Toolkit) ConnOAuthStore() connoauth.Store
- func (t *Toolkit) Connection() string
- func (t *Toolkit) HasConnection(name string) bool
- func (t *Toolkit) HydrateSchemas(ctx context.Context)
- func (t *Toolkit) IndexItems(name string) (schemaHash string, items map[string]string, ok bool)
- func (*Toolkit) Kind() string
- func (t *Toolkit) ListConnections() []toolkit.ConnectionDetail
- func (t *Toolkit) LoadStoredSchema(ctx context.Context, name string) error
- func (t *Toolkit) Name() string
- func (t *Toolkit) Operations(name string) (ops []gqlschema.Operation, schemaHash string, ok bool)
- func (t *Toolkit) RefreshSchema(ctx context.Context, name string) error
- func (t *Toolkit) RegisterTools(s *mcp.Server)
- func (t *Toolkit) ReloadVectors(ctx context.Context, name string)
- func (t *Toolkit) RemoveConnection(name string) error
- func (t *Toolkit) SchemaInfo(name string) (SchemaInfo, error)
- func (t *Toolkit) SchemaInfos() []SchemaInfo
- func (t *Toolkit) SearchOperations(ctx context.Context, query string, perConnLimit int) []RankedConnectionOperation
- func (t *Toolkit) SetAuthEvents(w *authevents.Writer)
- func (t *Toolkit) SetConnOAuthStore(s connoauth.Store)
- func (t *Toolkit) SetEmbeddingProvider(p embedding.Provider)
- func (t *Toolkit) SetExportDeps(deps ExportDeps)
- func (t *Toolkit) SetMemBudget(b *membudget.Budget)
- func (t *Toolkit) SetMetrics(m *observability.Metrics)
- func (*Toolkit) SetQueryProvider(query.Provider)
- func (t *Toolkit) SetRoutePolicy(p RoutePolicy)
- func (t *Toolkit) SetSchema(ctx context.Context, name string, payload []byte) error
- func (t *Toolkit) SetSchemaStore(s SchemaStore)
- func (*Toolkit) SetSemanticProvider(semantic.Provider)
- func (t *Toolkit) SetVectorReader(r VectorReader)
- func (t *Toolkit) Tools() []string
- func (t *Toolkit) UpdateConnection(name string, config map[string]any) error
- type VectorReader
Constants ¶
const ( // Kind is the connection-instance kind discriminator. Operators see // this in the admin UI's connection picker. Kind = "graphql" // DefaultConnectTimeout caps the dial step on each call. DefaultConnectTimeout = upstreamauth.DefaultConnectTimeout // DefaultCallTimeout caps the total per-call time. DefaultCallTimeout = upstreamauth.DefaultCallTimeout // DefaultMaxResponseBytes is the upstream read cap: the most the // toolkit reads of any one response. DefaultMaxResponseBytes = upstreamauth.DefaultMaxResponseBytes // DefaultMaxInlineBytes is the inline budget: the most a rendered // graphql_query result may hold. It is a model-context budget, set // from what a client accepts (#1587, #1606) and matching the API // gateway's. A result past it has its data cut, is flagged with // data_truncated, and is steered to graphql_export, which streams // the whole response into an asset with no context cost. DefaultMaxInlineBytes = int64(32 * 1024) // DefaultMaxQueryDepth caps the selection depth of a document the // toolkit will send. A deeply nested document is how a GraphQL // endpoint is made to do unbounded work from one small request, and // fifteen is deeper than any document graphql_discover renders. DefaultMaxQueryDepth = 15 // DefaultMaxPages caps a paginated walk when the caller names no // limit of their own. DefaultMaxPages = 10 // SchemaValidationStrict refuses a document that does not validate // against the stored schema. The default: a document naming a field // the connection's schema does not have is a caller working from // the wrong schema, and sending it spends a call to learn that. SchemaValidationStrict = "strict" // SchemaValidationWarn sends the document anyway and reports the // violations alongside the upstream's answer. For a deployment // whose stored schema is behind the endpoint it serves, or which // uses a directive the compatibility-floor introspection query does // not record. SchemaValidationWarn = "warn" )
const ( AuthModeNone = upstreamauth.AuthModeNone AuthModeBearer = upstreamauth.AuthModeBearer AuthModeAPIKey = upstreamauth.AuthModeAPIKey AuthModeBasic = upstreamauth.AuthModeBasic AuthModeOAuth = upstreamauth.AuthModeOAuth AuthModeOAuth2ClientCredentials = upstreamauth.AuthModeOAuth2ClientCredentials AuthModeOAuth2AuthorizationCode = upstreamauth.AuthModeOAuth2AuthorizationCode AuthModeSignedJWT = upstreamauth.AuthModeSignedJWT AuthModeMTLS = upstreamauth.AuthModeMTLS CredentialPlacementHeader = upstreamauth.CredentialPlacementHeader CredentialPlacementQuery = upstreamauth.CredentialPlacementQuery DefaultAPIKeyHeader = upstreamauth.DefaultAPIKeyHeader OAuth2AuthStyleHeader = upstreamauth.OAuth2AuthStyleHeader OAuth2AuthStyleParams = upstreamauth.OAuth2AuthStyleParams )
The credential vocabulary an operator configures on a graphql connection. The values are defined by internal/upstreamauth, which owns the outbound authentication policy for every HTTP-based connection kind; they are aliased here because they are part of this toolkit's public API and of what an operator types into auth_mode.
const ( SignedJWTAlgHS256 = upstreamauth.SignedJWTAlgHS256 SignedJWTAlgRS256 = upstreamauth.SignedJWTAlgRS256 SignedJWTAlgES256 = upstreamauth.SignedJWTAlgES256 DefaultSignedJWTTokenLifetime = upstreamauth.DefaultSignedJWTTokenLifetime DefaultSignedJWTIssuedAtSkew = upstreamauth.DefaultSignedJWTIssuedAtSkew )
The signing algorithms auth_mode=signed_jwt supports, and the defaults an unset lifetime and skew take. Aliased from the shared seam for the same reason as the mode names above.
const ( // DiscoverLevelOperations is a ranked list of operations. DiscoverLevelOperations = "operations" // DiscoverLevelOperation is one operation's arguments, return shape // and runnable skeleton. DiscoverLevelOperation = "operation" )
The two depths graphql_discover answers at, reported in DiscoverOutput.Level so a caller can branch on the shape it received rather than on which keys happen to be present.
const ( // StoppedByEnd is the upstream saying there is no next page. StoppedByEnd = "end" // StoppedByMaxPages is the walk's own page bound. StoppedByMaxPages = "max_pages" // StoppedByError is a page the upstream refused; the errors are on // the result. StoppedByError = "error" )
Why a walk stopped, reported as PaginationReport.StoppedBy.
const ( // SchemaSourceIntrospection marks a schema read from the endpoint. SchemaSourceIntrospection = "introspection" // SchemaSourceUpload marks a schema an operator supplied through // the admin route, which is the path for an endpoint with // introspection disabled. SchemaSourceUpload = "upload" )
Schema provenance values recorded on a stored schema, so an operator reading a connection knows whether what the platform holds came from the endpoint or from them.
const ( // ToolDiscover finds an operation and describes it. ToolDiscover = "graphql_discover" // ToolQuery executes one document. ToolQuery = "graphql_query" // ToolExport streams one document's result into an asset. ToolExport = "graphql_export" )
Tool names this toolkit registers. Exported so audit code, persona configuration and tests reference the same literals as the registration site.
Variables ¶
var ( // ErrConnectionExists is returned when AddConnection is called with // a name already registered. ErrConnectionExists = errors.New("graphql: connection already exists") // ErrConnectionNotFound is returned when an operation is requested // against a connection that has not been registered. ErrConnectionNotFound = errors.New("graphql: connection not found") )
Errors the connection registry answers with.
var ErrNeedsReauth = upstreamauth.ErrNeedsReauth
ErrNeedsReauth is the structured error a tool surfaces when an authorization_code connection's stored refresh token is missing, expired, or definitively rejected by the IdP. Transient failures (network, 5xx, cancellation) do not produce it.
var ErrSchemaNotFound = errors.New("graphql: no stored schema for connection")
ErrSchemaNotFound reports a connection with no stored schema.
Functions ¶
This section is empty.
Types ¶
type Authenticator ¶
type Authenticator = upstreamauth.Authenticator
Authenticator applies a connection's authentication scheme to an outbound HTTP request. The implementations and every auth mode live in internal/upstreamauth, shared with the platform's other HTTP-based connection kinds; this alias keeps the toolkit's own vocabulary intact at its call sites.
func NewAuthenticator ¶
func NewAuthenticator(c Config) (Authenticator, error)
NewAuthenticator returns the Authenticator implementation for a validated Config.
type Config ¶
type Config struct {
// EndpointURL is the full URL documents are POSTed to (e.g.
// "https://datahub.example.com/api/graphql"). Required. Unlike the
// API gateway's base_url this is the whole address, not a root
// paths are joined to: a GraphQL endpoint has one address.
EndpointURL string
// Description is an optional human-readable description of the
// connection, surfaced by ListConnections and so by the admin UI
// and the list_connections tool. Empty falls back to the endpoint.
Description string
// ConnectionName is the audit-visible connection identifier and the
// value passed in a tool's `connection` argument. Populated from
// the toolkit instance name.
ConnectionName string
// AuthMode and the credential fields below carry the shared
// upstream authentication policy. See internal/upstreamauth.
AuthMode string
Credential string
CredentialPlacement string
APIKeyHeader string
APIKeyParam string
Username string
Password string
OAuth2 OAuth2Config
// SignedJWT carries the assertion parameters used when AuthMode is
// AuthModeSignedJWT: the platform mints a short-lived JWT per call
// from an identifier and a signing key issued out of band. Aliased
// straight from the shared seam rather than mirrored, because
// nothing in it is this kind's to define.
SignedJWT SignedJWTConfig
// ConnectTimeout caps the dial step on each call.
ConnectTimeout time.Duration
// CallTimeout caps the total per-call time.
CallTimeout time.Duration
// MaxResponseBytes is the upstream read cap.
MaxResponseBytes int64
// MaxInlineBytes is the most of a response returned through a tool
// result. The read cap bounds it, so a connection whose
// MaxResponseBytes is lower returns at most that.
MaxInlineBytes int64
// StaticHeaders are operator-configured headers attached to every
// outbound request, in addition to whatever AuthMode contributes.
// This is where an upstream's tenant or folder routing goes (Sage
// X3's x-xtrem-endpoint, a vendor subscription key). The model
// never sets or overrides these.
StaticHeaders map[string]string
// MTLSClientCertPEM is the PEM client certificate chain presented
// during the TLS handshake.
MTLSClientCertPEM string
// MTLSClientKeyPEM is the PEM private key matching the certificate.
// Encrypted at rest.
MTLSClientKeyPEM string
// TLSCABundlePEM is an optional PEM bundle of root CAs added to the
// trust store for this connection's outbound requests.
TLSCABundlePEM string
// IdentityPassthrough forwards the acting caller's inbound bearer
// token as the outbound Authorization header instead of applying
// this connection's shared credential.
IdentityPassthrough bool
// SchemaValidation is SchemaValidationStrict (default) or
// SchemaValidationWarn.
SchemaValidation string
// MaxQueryDepth caps the selection depth of a document the toolkit
// will send. Defaults to DefaultMaxQueryDepth.
MaxQueryDepth int
// NamespaceDepth caps how many segments a dotted operation id may
// have when the schema is walked into operations. Defaults to
// gqlschema.DefaultNamespaceDepth.
NamespaceDepth int
// ReadOnly refuses every mutation document on this connection, for
// every persona. It is the connection-level counterpart to a
// persona's `deny` rule on the MUTATION method: an operator who
// mounts an ERP for reporting sets it once here rather than in
// every persona.
ReadOnly bool
}
Config holds the configuration of one GraphQL connection.
func ParseConfig ¶
ParseConfig parses a Config from the generic map a connection is stored as and applies defaults. The returned Config is fully validated.
func (Config) IsOAuthAuthorizationCode ¶
IsOAuthAuthorizationCode reports whether the connection uses the OAuth authorization_code grant. The admin redirect handler and the kind handler gate the one-time browser flow on this rather than on the raw auth_mode string shape.
func (Config) Validate ¶
Validate returns an error when the configuration is missing required fields or holds invalid values. The auth, timeout, static-header, passthrough and TLS rules belong to internal/upstreamauth and are called individually so this kind's own checks stay interleaved in the order an operator reads them.
type DiscoverInput ¶
type DiscoverInput struct {
Connection string `json:"connection"`
Query string `json:"query,omitempty"`
OperationID string `json:"operation_id,omitempty"`
Limit int `json:"limit,omitempty"`
Ranking string `json:"ranking,omitempty"`
Depth int `json:"depth,omitempty"`
}
DiscoverInput is the parsed argument shape for graphql_discover.
type DiscoverOutput ¶
type DiscoverOutput struct {
Level string `json:"level"`
Connection string `json:"connection"`
Operations []RankedOperation `json:"operations,omitempty"`
Operation *OperationDetail `json:"operation,omitempty"`
// SchemaHash and SchemaFetchedAt identify the schema version this
// answer was read from, so a caller comparing two answers can see
// whether the schema moved underneath them.
SchemaHash string `json:"schema_hash,omitempty"`
SchemaFetchedAt string `json:"schema_fetched_at,omitempty"`
// MatchedLexical and ShownSemantic report where relevance ended:
// how many operations contain every token, and how many followed
// them as neighbors by intent. Absent unless the call carried a
// query.
MatchedLexical *int `json:"matched_lexical,omitempty"`
ShownSemantic *int `json:"shown_semantic,omitempty"`
Note string `json:"note,omitempty"`
Next string `json:"next,omitempty"`
}
DiscoverOutput is the structured result at both levels. Level names the shape; exactly one of Operations and Operation is populated for it. Next says what argument goes one level deeper.
type Error ¶
type Error struct {
// Message is the upstream's own text. It is passed through
// unchanged: for most GraphQL upstreams it is the only diagnosis
// the caller will get.
Message string `json:"message"`
// Path is the response path the error occurred at, when the
// upstream reports one.
Path []any `json:"path,omitempty"`
// Locations are the document positions the upstream blames.
Locations []ErrorLocation `json:"locations,omitempty"`
// Extensions is the upstream's own error metadata (an error code,
// a classification), passed through as sent.
Extensions map[string]any `json:"extensions,omitempty"`
}
Error is one entry of a GraphQL response's errors array. A GraphQL endpoint reports a failure this way inside an HTTP 200, which is why the platform classifies the outcome from the body rather than from the status line.
type ErrorLocation ¶
ErrorLocation is a line and column in the submitted document.
type ExportAsset ¶
type ExportAsset struct {
ID string
OwnerID string
OwnerEmail string
Name string
Description string
ContentType string
S3Bucket string
S3Key string
SizeBytes int64
Tags []string
Provenance ExportProvenance
SessionID string
IdempotencyKey string
}
ExportAsset is the row inserted into the portal's assets when a graphql_export call succeeds.
type ExportAssetRef ¶
ExportAssetRef is what an idempotency-key lookup returns.
type ExportAssetStore ¶
type ExportAssetStore interface {
InsertExportAsset(ctx context.Context, asset ExportAsset) error
GetByIdempotencyKey(ctx context.Context, ownerID, key string) (*ExportAssetRef, error)
}
ExportAssetStore is the subset of the portal asset store graphql_export writes through.
type ExportConfig ¶
ExportConfig holds the platform-level limits for graphql_export.
type ExportDeps ¶
type ExportDeps struct {
AssetStore ExportAssetStore
VersionStore ExportVersionStore
S3Client ExportS3Client
// ResourceLander lands a result in a managed resource by path instead of in
// a new asset (#1663). nil leaves the asset destination the only one, which
// is what a deployment with no managed-resource library has.
ResourceLander toolkit.ResourceLander
S3Bucket string
S3Prefix string
BaseURL string
Config ExportConfig
GetUserContext func(ctx context.Context) *ExportUserContext
}
ExportDeps holds the platform-side dependencies graphql_export needs. A nil AssetStore is export disabled: the tool is not registered, so the model never sees one it could not successfully call.
type ExportProvenance ¶
type ExportProvenance struct {
ToolCalls []ExportProvenanceCall
SessionID string
UserID string
}
ExportProvenance records the call that produced an asset, so a portal viewer can render where its content came from.
type ExportProvenanceCall ¶
ExportProvenanceCall is one step in the provenance chain.
type ExportS3Client ¶
type ExportS3Client interface {
// PutObjectStream uploads body to bucket/key, returning the bytes
// written.
PutObjectStream(ctx context.Context, bucket, key string, body io.Reader, contentType string) (size int64, err error)
}
ExportS3Client is the object storage graphql_export writes to.
type ExportShareCreator ¶
type ExportShareCreator interface {
}
ExportShareCreator creates a public share link for an exported asset. nil disables public-link creation.
type ExportUserContext ¶
ExportUserContext is the caller's identity, supplied by the platform through a callback so the toolkit does not import the middleware.
type ExportVersion ¶
type ExportVersion struct {
ID string
AssetID string
S3Key string
S3Bucket string
ContentType string
SizeBytes int64
CreatedBy string
ChangeSummary string
}
ExportVersion is the row inserted into the portal's asset versions.
type ExportVersionStore ¶
type ExportVersionStore interface {
CreateExportVersion(ctx context.Context, version ExportVersion) (int, error)
}
ExportVersionStore is the subset of the portal version store graphql_export writes through.
type MultiConfig ¶
MultiConfig holds parsed per-connection configs plus the aggregate toolkit's default connection name.
func ParseMultiConfig ¶
ParseMultiConfig validates and returns the parsed config for every instance. Per-instance parse errors are logged and the bad instance is skipped so one misconfigured connection cannot block startup.
type OAuth2Config ¶
type OAuth2Config struct {
// Grant is the OAuth flow: client_credentials or
// authorization_code.
Grant string
// TokenURL is the upstream's token endpoint.
TokenURL string
// ClientID is the platform's registered client id.
ClientID string
// ClientSecret is the platform's registered client secret,
// encrypted at rest.
ClientSecret string
// Scopes is an optional list of scopes to request.
Scopes []string
// EndpointAuthStyle is "header" (default) or "params".
EndpointAuthStyle string
// AuthorizationURL is the upstream's authorization endpoint,
// required for the authorization_code grant.
AuthorizationURL string
// Prompt is an optional OIDC prompt parameter.
Prompt string
}
OAuth2Config describes the OAuth parameters used when AuthMode is the canonical oauth mode. Mirrors the API gateway's, because both are projections of the same shared seam.
type OAuthKindHandler ¶
type OAuthKindHandler struct {
// contains filtered or unexported fields
}
OAuthKindHandler adapts this kind onto the platform's unified connection-OAuth flow, so a GraphQL connection using the authorization_code grant is connected, reconnected and revoked through the same admin surface and the same token store as every other kind. Registered at startup in the platform's HTTP wiring.
func NewOAuthKindHandler ¶
func NewOAuthKindHandler(tk *Toolkit) *OAuthKindHandler
NewOAuthKindHandler builds the handler for a toolkit.
func (*OAuthKindHandler) AfterConnect ¶
AfterConnect reads the connection's schema now that a credential exists. A GraphQL endpoint behind an authorization_code grant refuses introspection until the flow completes, so the connection registered with no schema; this is the first moment it can have one.
func (*OAuthKindHandler) ParseOAuthConfig ¶
ParseOAuthConfig validates a connection's stored config and maps its OAuth settings into a connoauth.Config. It reports an error when the connection is not configured for the authorization_code grant, which the unified handler renders as HTTP 409.
The mapping is delegated to the shared seam's ConnOAuthConfig so the initial code exchange here and the per-call silent refresh in the authenticator read every field through one translator.
type OperationDetail ¶
type OperationDetail struct {
OperationSummary
// ArgumentDetails are the operation's arguments with their types,
// descriptions, defaults and whether they are required.
ArgumentDetails []gqlschema.Argument `json:"argument_details,omitempty"`
// InputTypes expands the input-object types the arguments
// reference, so a caller filling in a filter or a create payload
// does not need a second lookup.
InputTypes []gqlschema.InputType `json:"input_types,omitempty"`
// ReturnShape is the return type's field tree, depth-limited.
ReturnShape []gqlschema.FieldNode `json:"return_shape,omitempty"`
// Skeleton is a document that validates against this connection's
// schema and calls this operation, with every argument bound to a
// variable. It is the load-bearing part of this level: it is the
// difference between a correct selection on the first try and
// several calls spent on validation errors.
Skeleton string `json:"skeleton"`
// Variables is a JSON object carrying one entry per required
// argument, ready to edit and pass as graphql_query's variables.
// An optional argument is declared in the skeleton but absent here,
// so leaving it out sends the schema's own default; add its key to
// set it.
Variables string `json:"variables"`
}
OperationDetail is one operation at the operation level: everything needed to write the call, plus a document that already makes it.
type OperationSummary ¶
type OperationSummary struct {
// OperationID is the kind-prefixed dotted id
// ("query:masterData.product.query"). It is what operation_id
// takes.
OperationID string `json:"operation_id"`
// Kind is QUERY or MUTATION. It is also the method a persona rule
// names for this operation.
Kind string `json:"kind"`
// Path is the path a persona rule names this operation under: the
// dotted id with dots as slashes.
Path string `json:"path"`
// Summary is the descriptions the schema carries along the
// operation's path.
Summary string `json:"summary,omitempty"`
// ReturnType is the rendered type the operation returns.
ReturnType string `json:"return_type,omitempty"`
// Arguments are the operation's argument names, rendered
// "name: Type" so a caller can see what it takes without a second
// call.
Arguments []string `json:"arguments,omitempty"`
// Deprecated reports the schema marking this operation
// @deprecated.
Deprecated bool `json:"deprecated,omitempty"`
}
OperationSummary is the slim per-operation view a ranked list returns. It carries what a caller needs to choose an operation and to ask for it by id, and nothing more: the full argument and return detail is one call away behind operation_id.
type PaginateInput ¶
type PaginateInput struct {
// Items is the dotted path, inside the response's data object, of
// the array merged across pages
// ("masterData.product.query.edges", "searchAcrossEntities.results").
// Required.
Items string `json:"items"`
// CursorVariable is the document variable the next page's cursor is
// bound to ("after", "scrollId"). Required: the cursor goes back as
// a variable, so the document itself is unchanged between pages.
CursorVariable string `json:"cursor_variable"`
// NextCursorPath is the dotted path, inside data, holding the next
// page's cursor. Defaults to the Relay pageInfo.endCursor beside
// the items array.
NextCursorPath string `json:"next_cursor_path,omitempty"`
// HasNextPath is the dotted path, inside data, of a boolean saying
// whether another page exists. Defaults to the Relay
// pageInfo.hasNextPage beside the items array. An upstream that
// signals the end by a null cursor alone needs no such field: the
// walk stops on an absent cursor either way.
HasNextPath string `json:"has_next_path,omitempty"`
// MaxPages bounds the walk. Defaults to DefaultMaxPages.
MaxPages int `json:"max_pages,omitempty"`
}
PaginateInput is the walk a caller asks for. It names the array to merge and the variable the next page's cursor is fed back into; everything else has a Relay default.
type PaginationReport ¶
type PaginationReport struct {
// PagesFetched is how many pages were read.
PagesFetched int `json:"pages_fetched"`
// ItemsMerged is the length of the merged array.
ItemsMerged int `json:"items_merged"`
// StoppedBy is why the walk ended.
StoppedBy string `json:"stopped_by"`
// NextCursor is the cursor the next page would have used, present
// when the walk stopped at its page bound rather than at the end.
NextCursor string `json:"next_cursor,omitempty"`
}
PaginationReport says what a walk did.
type QueryInput ¶
type QueryInput struct {
Connection string `json:"connection"`
Query string `json:"query"`
Variables json.RawMessage `json:"variables,omitempty"`
OperationName string `json:"operation_name,omitempty"`
TimeoutSeconds int `json:"timeout_seconds,omitempty"`
Paginate *PaginateInput `json:"paginate,omitempty"`
}
QueryInput is the parsed argument shape for graphql_query.
Variables is raw because the schema admits two forms: the object a GraphQL client sends, and a string holding that object's JSON, which is what a client that stringifies structured arguments sends. Both reach the same upstream request (#1548).
type QueryOutput ¶
type QueryOutput struct {
Connection string `json:"connection"`
// Kind is QUERY or MUTATION: the operation kind that executed, and
// the method the persona rules authorized it under.
Kind string `json:"kind"`
// OperationName is the operation that ran, when the document named
// one.
OperationName string `json:"operation_name,omitempty"`
// Operations are the dotted operation ids this document invoked,
// the same ids graphql_discover reports and persona rules name.
Operations []string `json:"operations,omitempty"`
// Status is the HTTP status the endpoint answered with. It is
// almost always 200, including for a failure: what decides the
// outcome is upstream_error.
Status int `json:"status"`
// Data is the GraphQL data object, as sent. Present even alongside
// errors: a partial result is preserved rather than discarded.
Data json.RawMessage `json:"data,omitempty"`
// Errors is the response's errors array, passed through unchanged.
Errors []Error `json:"errors,omitempty"`
// Extensions is the response's extensions object, passed through.
Extensions map[string]any `json:"extensions,omitempty"`
// UpstreamError reports a call that failed however it was
// transported: a non-2xx, or a 200 carrying errors. It is what the
// platform's audit, call catalog and metrics classify the call on.
UpstreamError bool `json:"upstream_error"`
// ValidationWarnings are the schema violations found in a
// connection whose schema_validation is warn. Empty under strict,
// where a violation refuses the call instead.
ValidationWarnings []string `json:"validation_warnings,omitempty"`
// DataBytes is the size of the data read.
DataBytes int `json:"data_bytes"`
// DataTruncated reports data withheld because the rendered result
// would exceed this connection's max_inline_bytes. A cut JSON
// document cannot be parsed, so the data is omitted rather than
// halved; export_arguments carries the call that streams it whole.
DataTruncated bool `json:"data_truncated,omitempty"`
// ExportArguments is the graphql_export call that writes this same
// result to an asset, present when the data did not fit inline.
ExportArguments map[string]any `json:"export_arguments,omitempty"`
// Pagination reports a walk that ran.
Pagination *PaginationReport `json:"pagination,omitempty"`
// Note explains anything that changed the answer.
Note string `json:"note,omitempty"`
}
QueryOutput is what a caller gets back from one document.
type RankedConnectionOperation ¶
type RankedConnectionOperation struct {
Connection string
Operation gqlschema.Operation
Score float64
}
RankedConnectionOperation is one operation matched by SearchOperations, tagged with the connection it belongs to and its score under the ranking that produced it. The score is comparable within a connection; across connections it is best-effort, because an indexed connection scores by cosine while one that fell back to lexical scores positionally.
type RankedOperation ¶
type RankedOperation struct {
OperationSummary
Score *float64 `json:"score,omitempty"`
LexicalMatch *bool `json:"lexical_match,omitempty"`
}
RankedOperation is one operation in a list, plus what put it there when a query ranked it. Score and LexicalMatch are pointers because both are absent from an unranked list and a zero score is a real score.
type RankingMode ¶
type RankingMode string
RankingMode selects how graphql_discover scores an operation against the caller's query. The three modes and the arithmetic behind them are the platform's, shared with the API gateway through internal/opranking, so a caller's experience of relevance does not depend on which kind their connection is.
const ( // RankingLexical is the substring AND filter: every token of the // query must appear in the operation's text. Deterministic and // needs no embedding provider. RankingLexical RankingMode = RankingMode(opranking.ModeLexical) // RankingSemantic ranks by embedding cosine similarity alone. RankingSemantic RankingMode = RankingMode(opranking.ModeSemantic) // RankingHybrid blends the lexical signal with the cosine. It is // what an omitted ranking resolves to whenever the connection has // an embedding index. RankingHybrid RankingMode = RankingMode(opranking.ModeHybrid) )
RankingMode values exposed on the graphql_discover schema.
func ParseRankingMode ¶
func ParseRankingMode(s string) (RankingMode, error)
ParseRankingMode resolves the caller's ranking argument. An empty value is resolved by the caller, which upgrades it to hybrid when the connection has an index.
type RoutePolicy ¶
type RoutePolicy interface {
Allow(ctx context.Context, connection, method, path, template string) (allowed bool, reason string)
}
RoutePolicy gates a GraphQL call by (connection, method, path) on top of the platform's tool and connection authorization. The method is the operation kind (QUERY or MUTATION) and the path is the dotted operation id with dots as slashes, which puts a GraphQL operation into the same space a persona's api_routes rules already evaluate.
The template argument is always equal to path here: a GraphQL operation id carries no parameters to substitute, so the two forms an HTTP route has collapse to one.
type SchemaInfo ¶
type SchemaInfo struct {
Connection string `json:"connection"`
Hash string `json:"schema_hash,omitempty"`
Source string `json:"source,omitempty"`
FetchedAt time.Time `json:"fetched_at,omitzero"`
OperationCount int `json:"operation_count"`
Error string `json:"error,omitempty"`
}
SchemaInfo is what an operator surface reports about a connection's schema: which version the platform holds, where it came from, when, how many operations it exposes, and why the last read failed when it did. A failed read leaves the schema the connection held in place, so Error beside a hash is a schema that survived a re-read the endpoint refused; Error with no hash is a connection that has never had one.
type SchemaStore ¶
type SchemaStore interface {
// GetSchema returns the stored schema for a connection, or an error
// wrapping ErrSchemaNotFound when there is none.
GetSchema(ctx context.Context, connection string) (StoredSchema, error)
// PutSchema writes a connection's schema, replacing any previous
// one.
PutSchema(ctx context.Context, s StoredSchema) error
// DeleteSchema removes a connection's schema, called when the
// connection is deleted.
DeleteSchema(ctx context.Context, connection string) error
}
SchemaStore persists a connection's schema. A deployment without one (no database) still works: every connection introspects at registration and holds its schema in memory for the process's life. What the store buys is a restart that does not re-read every endpoint, and an operation index that survives one.
type SignedJWTConfig ¶
type SignedJWTConfig = upstreamauth.SignedJWTConfig
SignedJWTConfig describes the assertion the platform mints when AuthMode is AuthModeSignedJWT. Defined by internal/upstreamauth, which owns the mode for every HTTP-based connection kind; aliased here because it is part of this toolkit's public API.
type StoredSchema ¶
type StoredSchema struct {
// Connection is the connection name the schema belongs to.
Connection string
// Hash is the sha256 of the SDL, hex-encoded. An operation index
// and its embeddings are keyed on it.
Hash string
// SDL is the schema text.
SDL string
// Source is SchemaSourceIntrospection or SchemaSourceUpload.
Source string
// FetchedAt is when the schema was read or uploaded.
FetchedAt time.Time
}
StoredSchema is one connection's schema as it is kept between restarts: the SDL, the hash that identifies it, where it came from, and when it was read. FetchedAt is what a strict-mode refusal names, so a caller working from a newer schema than the platform holds can see that is what happened.
type Toolkit ¶
type Toolkit struct {
// contains filtered or unexported fields
}
Toolkit is the graphql toolkit. One Toolkit manages every registered GraphQL connection, each addressing a different endpoint. Connections are added at startup from the platform's merged YAML+DB config, or at runtime by the admin REST handler when an operator saves one through the portal.
func NewMulti ¶
func NewMulti(cfg MultiConfig) *Toolkit
NewMulti creates the toolkit from every configured instance. Per-connection materialization failures (an authenticator that cannot be built) are logged and skipped so one bad connection cannot block platform startup. Endpoint failures happen at call time and are surfaced through the tool's response, not at startup.
func (*Toolkit) AddConnection ¶
AddConnection registers a connection at runtime from the generic config map the admin API stores, and reads its schema. Satisfies toolkit.ConnectionManager.
The read goes to the endpoint first and the store second: a connection created here is new to this process, and what the store holds for it (a schema another replica read or was handed) is what serves it when the endpoint will not (#1676).
func (*Toolkit) ConnOAuthStore ¶
ConnOAuthStore returns the wired OAuth token store, or nil.
func (*Toolkit) Connection ¶
Connection returns the default connection name for audit logging.
func (*Toolkit) HasConnection ¶
HasConnection reports whether a connection is registered.
func (*Toolkit) HydrateSchemas ¶
HydrateSchemas brings every registered connection's schema up: the stored one when there is one, a fresh introspection otherwise. The platform calls it once after wiring the schema store, so a restart does not re-read every endpoint and a first start reads them all.
Connections are hydrated concurrently. They are independent network reads against different endpoints, and doing them in sequence would make startup cost the sum of every upstream's latency rather than the slowest one's.
Failures are recorded on the connection and logged, never returned: an endpoint that is down at startup must not stop the platform serving every other connection. The caller bounds the whole pass with the context it passes.
func (*Toolkit) IndexItems ¶
IndexItems returns the text each of a connection's operations is embedded from, keyed by operation id, together with the schema hash those operations belong to. It is what the platform's index-jobs consumer reads: the toolkit owns what an operation's indexable text is, and the consumer owns where the resulting vectors are written.
func (*Toolkit) ListConnections ¶
func (t *Toolkit) ListConnections() []toolkit.ConnectionDetail
ListConnections enumerates the registered connections for list_connections and the admin UI. OperationCount is how many operations the current schema exposes, so an operator can see at a glance whether a connection's schema was read.
func (*Toolkit) LoadStoredSchema ¶ added in v1.131.1
LoadStoredSchema installs the schema the store holds for a connection, replacing whatever this instance holds and clearing any failure it recorded. It is how a schema stored by another replica, an upload or a re-read, reaches this one: the reload bus calls it when a peer announces one. The store's answer is final because it is what every replica shares; this instance's own last read is superseded by it. An instance with no store has nothing to load and is left as it is.
func (*Toolkit) Operations ¶
Operations returns a connection's current operation index together with the schema hash it belongs to. The index-jobs source reads it to build the text it embeds.
func (*Toolkit) RefreshSchema ¶
RefreshSchema reads a connection's schema from its endpoint by introspection, stores it, and rebuilds the operation index. It is what the admin refresh action calls, and what a connection falls back to when nothing is stored.
An endpoint with introspection disabled fails here with a message saying so; that message is recorded on the connection and reported by SchemaInfo, so the state is a named cause rather than an operation index that is silently empty.
func (*Toolkit) RegisterTools ¶
RegisterTools registers this toolkit's tools with the MCP server.
func (*Toolkit) ReloadVectors ¶
ReloadVectors re-reads a connection's persisted embeddings. The index-jobs consumer calls it after a successful pass so a connection that was ranking lexically starts ranking semantically without a restart.
func (*Toolkit) RemoveConnection ¶
RemoveConnection drops a connection and closes its idle transports. It is the deletion: the stored schema is dropped with the connection, so one that is gone does not leave an operation index behind for a later connection of the same name to inherit. A configuration change arrives through UpdateConnection instead.
func (*Toolkit) SchemaInfo ¶
func (t *Toolkit) SchemaInfo(name string) (SchemaInfo, error)
SchemaInfo reports what the platform holds for one connection.
func (*Toolkit) SchemaInfos ¶
func (t *Toolkit) SchemaInfos() []SchemaInfo
SchemaInfos reports every registered connection's schema state, for the admin surface and for the index-jobs source's gap detection.
func (*Toolkit) SearchOperations ¶
func (t *Toolkit) SearchOperations(ctx context.Context, query string, perConnLimit int) []RankedConnectionOperation
SearchOperations ranks operations across every connection on this toolkit against a free-form query, returning up to perConnLimit per connection. It is the federation seam behind the universal search tool's endpoints group: the same ranking graphql_discover exposes, aggregated across connections instead of scoped to one.
Per-connection route policy is applied first, so a federated search never surfaces an operation a scoped graphql_discover call would have hidden.
func (*Toolkit) SetAuthEvents ¶
func (t *Toolkit) SetAuthEvents(w *authevents.Writer)
SetAuthEvents wires the audit-event writer into the toolkit and into every already-materialized authenticator, so an outbound token refresh emits its lifecycle event.
func (*Toolkit) SetConnOAuthStore ¶
SetConnOAuthStore wires the unified OAuth token store, required for the authorization_code grant, and re-threads it through every already-materialized authenticator.
func (*Toolkit) SetEmbeddingProvider ¶
SetEmbeddingProvider wires the provider that embeds a caller's query for semantic and hybrid ranking. Operation vectors are never computed here: they are written by the platform's index-jobs consumer and read through the VectorReader.
func (*Toolkit) SetExportDeps ¶
func (t *Toolkit) SetExportDeps(deps ExportDeps)
SetExportDeps wires the platform-side dependencies for graphql_export.
func (*Toolkit) SetMemBudget ¶
SetMemBudget wires the shared in-flight memory budget the buffered tools reserve against before allocating a response buffer. Passing nil leaves the buffered path bounded only by the per-connection read cap.
func (*Toolkit) SetMetrics ¶
func (t *Toolkit) SetMetrics(m *observability.Metrics)
SetMetrics wires the observability recorder. Every send reads it at call time, so a connection registered before metrics were enabled records from the first call after (#1678).
func (*Toolkit) SetQueryProvider ¶
SetQueryProvider satisfies registry.Toolkit. See SetSemanticProvider.
func (*Toolkit) SetRoutePolicy ¶
func (t *Toolkit) SetRoutePolicy(p RoutePolicy)
SetRoutePolicy wires the per-operation authorization check.
func (*Toolkit) SetSchema ¶
SetSchema installs a schema an operator supplied, accepting either SDL or an introspection result. It is the path for an endpoint that disables introspection, where the platform cannot read the schema for itself. A payload that does not parse is the operator's input and is returned to them; it is not recorded on the connection, whose state is whatever it held before the attempt.
func (*Toolkit) SetSchemaStore ¶
func (t *Toolkit) SetSchemaStore(s SchemaStore)
SetSchemaStore wires the store a connection's schema is kept in between restarts. Passing nil leaves schemas in memory only.
func (*Toolkit) SetSemanticProvider ¶
SetSemanticProvider satisfies registry.Toolkit. A GraphQL endpoint carries its own schema and is not a table catalog, so there is nothing for the semantic layer to enrich here.
func (*Toolkit) SetVectorReader ¶
func (t *Toolkit) SetVectorReader(r VectorReader)
SetVectorReader wires the reader of persisted operation embeddings.
func (*Toolkit) Tools ¶
Tools returns the tool names this toolkit registers. graphql_export is present only when the platform wired the export dependencies, so the list matches what a client can actually call.
func (*Toolkit) UpdateConnection ¶ added in v1.131.1
UpdateConnection replaces a held connection's configuration and reads its schema again, keeping the schema it holds when the read fails. Satisfies toolkit.ConnectionUpdater, which is what makes a configuration save a change rather than a deletion followed by a registration: RemoveConnection drops the stored schema, and a save that went through it lost every schema an operator had supplied (#1676). A configuration that does not parse is refused with the connection left as it was.
type VectorReader ¶
type VectorReader interface {
// LoadVectors returns the persisted vectors for one connection's
// schema version, keyed by operation id. An empty map means the
// schema has not been indexed yet; ranking falls back to lexical
// and says so.
LoadVectors(ctx context.Context, connection, schemaHash string) (map[string][]float32, error)
}
VectorReader loads the operation embeddings written by the platform's index-jobs consumer. The toolkit only reads them: a connection never embeds its own operations on a request path, the same way the API gateway's connections never embed their catalog.