Help us shape the future of Go! Take the 2026 Go Developer Survey

representative

package
v0.7.0 Latest Latest
Warning

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

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

Documentation

Overview

Package representative exposes a deliberately small MCP interface to an external agent. It never exposes the seat/controller API or tool registry.

Index

Constants

This section is empty.

Variables

View Source
var (
	ErrUnauthenticated = errors.New("unauthenticated")
	ErrAuthUnavailable = errors.New("authentication unavailable")
)
View Source
var ErrInvalidConfig = errors.New("invalid representative authentication configuration")

Functions

func New

New returns a standalone handler. Mount it only on the dedicated external listener: there is intentionally no fallback to the privileged platform API.

Types

type Authenticator

type Authenticator interface {
	Authenticate(*http.Request) (Principal, error)
	Discovery(http.ResponseWriter, *http.Request)
	Challenge() string
}

Authenticator verifies every HTTP request independently, including requests made by a previously initialized MCP client.

type Config

type Config struct {
	ResourceURL string            `json:"resourceURL"`
	OAuth       *OAuthConfig      `json:"oauth,omitempty"`
	Principals  []PrincipalConfig `json:"principals"`
}

Config must be mounted from an operator-managed Secret, not embedded in public chart values. The whole file is validated anew on every request.

func LoadConfig

func LoadConfig(path string) (*Config, error)

LoadConfig opens the file each time, including following Kubernetes Secret volume symlink updates. Invalid, missing, or oversized files fail closed; the last successfully read configuration is deliberately never cached.

func (*Config) Validate

func (c *Config) Validate() error

Validate rejects ambiguous mappings and malformed policy before any credential is considered. Errors contain field descriptions, never values.

type ConversationStore

type ConversationStore interface {
	SendExternalMessage(context.Context, store.ExternalPrincipal, store.ExternalMessage) (*store.ExternalRequest, error)
	ExternalRequestStatus(context.Context, store.ExternalPrincipal, string) (*store.ExternalRequest, error)
	ReadExternalConversation(context.Context, store.ExternalPrincipal, string, int, int) (*store.ExternalConversation, error)
}

ConversationStore keeps acceptance, replies and idempotency durable.

type FileAuthenticator

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

FileAuthenticator reopens its Secret-backed configuration and validates every credential on every HTTP request. It does not cache either manual mappings or OAuth introspection results. Keep the mounted Secret file available and use a projected volume (not subPath) for Kubernetes rotation to take effect.

func NewFileAuthenticator

func NewFileAuthenticator(path string) (*FileAuthenticator, error)

NewFileAuthenticator checks configuration immediately so a misconfigured externally reachable listener never starts. Later read failures fail closed.

func (*FileAuthenticator) Authenticate

func (a *FileAuthenticator) Authenticate(r *http.Request) (Principal, error)

Authenticate accepts only one strict Authorization: Bearer header. Request bodies, cookies, tool arguments, and URL query parameters never provide an identity. The caller must separately verify that the mapped representative is active before reading or writing organization data.

func (*FileAuthenticator) Challenge

func (a *FileAuthenticator) Challenge() string

Challenge advertises only the validated, operator-configured public URL; untrusted Host or forwarded headers never determine the discovery address. On config failure it reveals no stale discovery information.

func (*FileAuthenticator) Discovery

func (a *FileAuthenticator) Discovery(w http.ResponseWriter, r *http.Request)

Discovery serves RFC 9728 protected-resource metadata with the SDK's CORS and method handling. Mount it at both the root and path-suffixed well-known routes. It exposes no client secret, principal mapping, or bearer digest.

type OAuthConfig

type OAuthConfig struct {
	Issuer           string `json:"issuer"`
	IntrospectionURL string `json:"introspectionURL"`
	ClientID         string `json:"clientID"`
	ClientSecret     string `json:"clientSecret"`
	RequiredScope    string `json:"requiredScope"`
}

OAuthConfig describes an existing authorization server, not an authorization server implemented by this gateway. It must support RFC 7662 introspection with client_secret_basic and return active, iss, aud, exp, sub, client_id, and scope. The sole accepted audience is Config.ResourceURL.

type Principal

type Principal struct {
	ID                    string `json:"id"`
	OrganizationID        string `json:"organizationID"`
	RepresentativeSeatKey string `json:"representativeSeatKey"`
	CallerID              string `json:"callerID"`
}

Principal is a trusted mapping from an external credential to one representative. None of these fields may come from MCP tool arguments.

type PrincipalConfig

type PrincipalConfig struct {
	Principal
	BearerSHA256  []string `json:"bearerSHA256,omitempty"`
	OAuthSubject  string   `json:"oauthSubject,omitempty"`
	OAuthClientID string   `json:"oauthClientID,omitempty"`
}

PrincipalConfig allows overlapping manual keys during rotation, or an exact OAuth subject/client pair, or both. BearerSHA256 holds lowercase hex SHA-256 digests, never plaintext keys. Generate keys from at least 32 random bytes: a digest alone cannot prove that its original key had sufficient entropy.

Jump to

Keyboard shortcuts

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