Documentation
¶
Overview ¶
Package controlplane owns Stella's deployment control-plane resources: LLM providers, deployment settings (embedding, CLI-tool registry, OAuth provider config), plugins (registered + manifest), and channels.
These resources are administered, not user-owned. Authorization is a single admin gate at Begin (see access.go): an Access is minted only for an admin authority, so a non-admin actor is denied before any durable read or external action — identical to the legacy requireAdmin gate this service replaces. There is no per-user ownership and no per-method authorization.
The service also owns the persistence and live-reload orchestration each control-plane mutation performs (store writes plus pool/plugin-host hot reloads), so the HTTP transport keeps only request decoding and response shaping. It never reads request-supplied identity: the caller passes a trusted authz.Authority derived from verified session claims.
Index ¶
- Constants
- Variables
- type Access
- func (a *Access) CliToolLatest(ctx context.Context, tool string) (string, error)
- func (a *Access) CreateProvider(ctx context.Context, p config.Provider) error
- func (a *Access) DeleteChannel(ctx context.Context, id string) error
- func (a *Access) DeleteOAuthProviderConfig(ctx context.Context, id string) error
- func (a *Access) DeleteProvider(ctx context.Context, id string) error
- func (a *Access) FetchProviderModels(ctx context.Context, id, apiKey, baseURL string) ([]ProviderModelItem, error)
- func (a *Access) GetChannel(ctx context.Context, id string) (config.Channel, error)
- func (a *Access) GetEmbeddingSettings(ctx context.Context) (config.EmbeddingSettings, error)
- func (a *Access) GetOAuthProviderConfig(ctx context.Context, id string) (connections.OAuthProviderConfig, error)
- func (a *Access) GetPluginConfig(ctx context.Context, kind, name string) (map[string]any, error)
- func (a *Access) GetPluginConfigSchema(ctx context.Context, kind, name string) (map[string]any, error)
- func (a *Access) GetPluginStatus(ctx context.Context, kind, name string) (any, error)
- func (a *Access) GetProvider(ctx context.Context, id string) (config.Provider, error)
- func (a *Access) ListChannels(ctx context.Context) ([]config.Channel, error)
- func (a *Access) ListManifestPlugins(ctx context.Context) (*manifestplugins.Manifest, error)
- func (a *Access) ListPlugins(ctx context.Context) ([]pkgplugins.RegisteredPlugin, error)
- func (a *Access) ListProviderModels(ctx context.Context, id string) ([]ProviderModelItem, error)
- func (a *Access) ListProviderTypes() ([]pluginhost.ProviderType, error)
- func (a *Access) ListProviders(ctx context.Context) ([]config.Provider, error)
- func (a *Access) LookupAgent(ctx context.Context, id string) (config.Agent, error)
- func (a *Access) ManageChannel(id string) (*ChannelManagement, error)
- func (a *Access) SaveChannel(ctx context.Context, ch config.Channel, cfgMap map[string]any, create bool) (config.Channel, error)
- func (a *Access) SaveManifestPlugins(ctx context.Context, plugins []manifestplugins.ManifestPlugin) (*manifestplugins.Manifest, error)
- func (a *Access) SearchCliToolRegistry(ctx context.Context, query string, limit int) ([]manifestplugins.RegistryTool, error)
- func (a *Access) SetEmbeddingSettings(ctx context.Context, upd EmbeddingUpdate) (config.EmbeddingSettings, error)
- func (a *Access) SetOAuthProviderConfig(ctx context.Context, cfg connections.OAuthProviderConfig) (connections.OAuthProviderConfig, error)
- func (a *Access) SyncManifestPlugins(ctx context.Context) (manifestplugins.ReconcileResult, error)
- func (a *Access) TogglePlugin(ctx context.Context, kind, name string, enabled bool) (config.Plugin, error)
- func (a *Access) UpdatePluginConfig(ctx context.Context, kind, name string, cfg map[string]any) (config.Plugin, error)
- func (a *Access) UpdateProvider(ctx context.Context, id string, p config.Provider) (config.Provider, error)
- type ChannelManagement
- func (m *ChannelManagement) Channel(ctx context.Context, id string) (config.Channel, error)
- func (m *ChannelManagement) Save(ctx context.Context, ch config.Channel, cfgMap map[string]any, create bool) (config.Channel, error)
- func (m *ChannelManagement) ValidateBinding(ctx context.Context, ch config.Channel) error
- type ConflictError
- type EmbeddingUpdate
- type ForbiddenError
- type NotFoundError
- type ProviderModelItem
- type PublicChannel
- type Service
- func (s *Service) Begin(_ context.Context, authority authz.Authority) (*Access, error)
- func (s *Service) EnabledChannelTypes(ctx context.Context, authority authz.Authority) (map[string]bool, error)
- func (s *Service) ListEnabledModels(ctx context.Context, authority authz.Authority) ([]config.CachedModel, error)
- func (s *Service) PublicChannels(ctx context.Context, authority authz.Authority) ([]PublicChannel, error)
- type UpstreamError
- type ValidationError
Constants ¶
const ChannelPluginConfigError = "channel instance config lives on /channels, not plugin config"
ChannelPluginConfigError is the client message returned when an admin tries to read or write a channel plugin's config through the plugin API; channel instance config lives on the /channels surface instead.
Variables ¶
ErrUnavailable is returned when the service itself is not configured (a nil receiver); the transport maps it to a fail-closed 503.
Functions ¶
This section is empty.
Types ¶
type Access ¶
type Access struct {
// contains filtered or unexported fields
}
Access is one authorized control-plane use case. Every control-plane resource (providers, settings, plugins, channels) is admin-only, so authorization is a single gate at Begin: an Access exists only for an admin authority. Each method then performs the durable write and hot-reload the legacy handler did, with no further per-method authorization.
func (*Access) CliToolLatest ¶
CliToolLatest resolves the latest installable version for a mise tool key.
func (*Access) CreateProvider ¶
CreateProvider persists a new provider and hot-reloads the pool.
func (*Access) DeleteChannel ¶
DeleteChannel stops a channel's runtime and removes it.
func (*Access) DeleteOAuthProviderConfig ¶
DeleteOAuthProviderConfig removes an OAuth provider client configuration.
func (*Access) DeleteProvider ¶
DeleteProvider removes a provider and hot-reloads the pool.
func (*Access) FetchProviderModels ¶
func (a *Access) FetchProviderModels(ctx context.Context, id, apiKey, baseURL string) ([]ProviderModelItem, error)
FetchProviderModels lists the provider's models from its live API, refreshes the cached set, and returns the merged list. Credentials fall back to the stored provider when the caller omits them. It preserves the legacy status split: a missing provider during the credential fallback is a 400 "api_key is required", while the authoritative load is a 404.
func (*Access) GetChannel ¶
GetChannel returns one channel by id (opaque 404 when missing).
func (*Access) GetEmbeddingSettings ¶
GetEmbeddingSettings returns the deployment-wide embedding configuration.
func (*Access) GetOAuthProviderConfig ¶
func (a *Access) GetOAuthProviderConfig(ctx context.Context, id string) (connections.OAuthProviderConfig, error)
GetOAuthProviderConfig returns the stored OAuth provider client configuration.
func (*Access) GetPluginConfig ¶
GetPluginConfig returns a plugin's stored config. Channel plugins are rejected: their instance config lives on /channels.
func (*Access) GetPluginConfigSchema ¶
func (a *Access) GetPluginConfigSchema(ctx context.Context, kind, name string) (map[string]any, error)
GetPluginConfigSchema returns a plugin's admin config schema.
func (*Access) GetPluginStatus ¶
GetPluginStatus returns a plugin's admin status payload.
func (*Access) GetProvider ¶
GetProvider returns one provider by id (opaque 404 when missing).
func (*Access) ListChannels ¶
func (*Access) ListManifestPlugins ¶
ListManifestPlugins returns the builtin manifest overlaid with DB overrides.
func (*Access) ListPlugins ¶
func (a *Access) ListPlugins(ctx context.Context) ([]pkgplugins.RegisteredPlugin, error)
ListPlugins returns the admin-visible registered plugins. The transport shapes each into its admin view.
func (*Access) ListProviderModels ¶
ListProviderModels returns the merged custom+fetched model list for a provider.
func (*Access) ListProviderTypes ¶
func (a *Access) ListProviderTypes() ([]pluginhost.ProviderType, error)
ListProviderTypes returns the provider plugin types the deployment can add.
func (*Access) ListProviders ¶
ListProviders returns every configured LLM provider.
func (*Access) LookupAgent ¶
LookupAgent reads an agent for a channel-binding precondition: a registration flow binds a channel to an agent that must exist and be enabled. It is an admin-gated read (the Access already passed Begin), so a non-admin never reaches it; the caller inspects the returned agent's Enabled flag.
func (*Access) ManageChannel ¶
func (a *Access) ManageChannel(id string) (*ChannelManagement, error)
ManageChannel opens a channel-management operation. The admin gate already ran at Begin, so this only hands back the operation handle; id is retained for call-site symmetry (registration flows keep this handle across their platform handshake, then call Save after credentials arrive).
func (*Access) SaveChannel ¶
func (a *Access) SaveChannel(ctx context.Context, ch config.Channel, cfgMap map[string]any, create bool) (config.Channel, error)
SaveChannel validates and persists a channel, ensures its plugin is enabled, and applies its runtime. create=true rejects an id that already exists (the create-only POST contract). It returns the reloaded channel.
func (*Access) SaveManifestPlugins ¶
func (a *Access) SaveManifestPlugins(ctx context.Context, plugins []manifestplugins.ManifestPlugin) (*manifestplugins.Manifest, error)
SaveManifestPlugins persists per-plugin overrides (definition and/or enabled toggle), re-registers the merged manifest, hot-reloads plugin tools/hooks, and returns the merged manifest.
func (*Access) SearchCliToolRegistry ¶
func (a *Access) SearchCliToolRegistry(ctx context.Context, query string, limit int) ([]manifestplugins.RegistryTool, error)
SearchCliToolRegistry searches the mise tool registry so the UI can add a CLI tool by name instead of a hand-written backend key.
func (*Access) SetEmbeddingSettings ¶
func (a *Access) SetEmbeddingSettings(ctx context.Context, upd EmbeddingUpdate) (config.EmbeddingSettings, error)
SetEmbeddingSettings persists the embedding configuration. The api_key is write-only: an omitted or empty key keeps the stored one. Enabling the lane without a key is rejected (it would silently no-op).
func (*Access) SetOAuthProviderConfig ¶
func (a *Access) SetOAuthProviderConfig(ctx context.Context, cfg connections.OAuthProviderConfig) (connections.OAuthProviderConfig, error)
SetOAuthProviderConfig persists an OAuth provider client configuration and returns the refreshed stored value.
func (*Access) SyncManifestPlugins ¶
func (a *Access) SyncManifestPlugins(ctx context.Context) (manifestplugins.ReconcileResult, error)
SyncManifestPlugins reconciles the merged manifest against the filesystem (installs binaries/skills) and returns the reconcile result.
func (*Access) TogglePlugin ¶
func (a *Access) TogglePlugin(ctx context.Context, kind, name string, enabled bool) (config.Plugin, error)
TogglePlugin enables/disables a plugin and hot-reloads its runtime. A sandbox backend pinned by STELLA_SANDBOX_BACKEND cannot be toggled.
func (*Access) UpdatePluginConfig ¶
func (a *Access) UpdatePluginConfig(ctx context.Context, kind, name string, cfg map[string]any) (config.Plugin, error)
UpdatePluginConfig validates and persists a plugin's config, then hot-reloads its runtime. Channel plugins are rejected (config lives on /channels).
func (*Access) UpdateProvider ¶
func (a *Access) UpdateProvider(ctx context.Context, id string, p config.Provider) (config.Provider, error)
UpdateProvider merges the request over the stored provider (preserving Type and defaulting Name), persists it, and hot-reloads the pool. It returns the merged provider so the transport can echo it.
type ChannelManagement ¶
type ChannelManagement struct {
// contains filtered or unexported fields
}
ChannelManagement is one channel-management operation. Its Save method owns the channel row plus the required channel plugin enable/apply as a single unit, so callers never need a second plugin call.
func (*ChannelManagement) Channel ¶
Channel reads the current row for this operation's channel so a caller can merge a partial update onto it. It is an admin-gated read (Begin already ran); a missing channel returns an error the caller treats as "start from a fresh row" rather than a hard failure.
func (*ChannelManagement) Save ¶
func (m *ChannelManagement) Save(ctx context.Context, ch config.Channel, cfgMap map[string]any, create bool) (config.Channel, error)
Save persists the already-authorized channel and applies its plugin as one control-plane operation. It intentionally makes no further authorization call.
func (*ChannelManagement) ValidateBinding ¶
ListChannels returns every configured channel. ValidateBinding checks the durable channel-binding invariant before an enrollment flow performs an external handshake. Save repeats the check and the database unique index closes the concurrent-write race.
type ConflictError ¶
type ConflictError struct{ Msg string }
ConflictError reports a create that collides with an existing resource, mapped to 409 by the transport. It is returned only after authorization succeeds.
func (*ConflictError) Error ¶
func (e *ConflictError) Error() string
type EmbeddingUpdate ¶
type EmbeddingUpdate struct {
Enabled bool
Model string
Dim int
BaseURL string
Normalize bool
APIKey *string
}
EmbeddingUpdate carries a validated embedding-settings write. APIKey is nil to keep the stored key (the GET never echoes it) or non-nil to replace it.
type ForbiddenError ¶
type ForbiddenError struct{ Msg string }
ForbiddenError reports a control-plane precondition that forbids an operation for a reason other than the admin gate (e.g. a resource locked by an environment override). It maps to 403 with Msg, distinct from the opaque authz.ErrForbidden denial, and is only ever returned after authorization succeeds so it never leaks to an unauthorized caller.
func (*ForbiddenError) Error ¶
func (e *ForbiddenError) Error() string
type NotFoundError ¶
type NotFoundError struct{ Msg string }
NotFoundError reports a control-plane resource that does not exist. Msg carries the historical per-resource client message so the transport preserves the 404 body byte-for-byte.
func (*NotFoundError) Error ¶
func (e *NotFoundError) Error() string
type ProviderModelItem ¶
type ProviderModelItem struct {
ID string `json:"id"`
Name string `json:"name,omitempty"`
Source string `json:"source"`
Enabled bool `json:"enabled"`
Config config.ProviderModel `json:"config,omitzero"`
}
ProviderModelItem is one merged model entry for a provider: custom (config-declared) models plus fetched (cached) models, unioned. Kept here with the persistence it derives from; the transport writes it directly.
type PublicChannel ¶
type PublicChannel struct {
ID string
Type string // effective type: the configured type, or the id when unset
AgentID string
Enabled bool
}
PublicChannel is the config-secret-free projection of a channel for the user-facing channel list. It deliberately omits the raw Config JSON that config.Channel carries (channel credentials), exposing only the fields the public list renders.
type Service ¶
type Service struct {
// contains filtered or unexported fields
}
Service owns the control-plane resources: the persistence and runtime handles a control-plane mutation needs to apply and hot-reload changes. Authorization is the admin gate in Begin (see access.go); a nil receiver fails closed.
func NewService ¶
func NewService(store config.Store, plugins *pluginhost.Host, pools *agent.PoolManager, conns *connections.Service, log *slog.Logger) *Service
NewService builds the control-plane service from its fully-wired dependencies. The composition root constructs it once and shares the same instance behind the HTTP endpoints. log defaults to slog.Default() when nil.
func (*Service) Begin ¶
Begin authorizes one control-plane use case. The control plane is administered, not user-owned: it validates the Authority and requires IsAdmin exactly once, so a non-admin or invalid authority fails closed here, before any durable read or external action — identical to the legacy requireAdmin gate this replaces. The handler never inspects identity beyond passing the trusted Authority.
func (*Service) EnabledChannelTypes ¶
func (s *Service) EnabledChannelTypes(ctx context.Context, authority authz.Authority) (map[string]bool, error)
EnabledChannelTypes returns the set of enabled channel-plugin names, used by the transport to hide channels whose plugin is disabled.
func (*Service) ListEnabledModels ¶
func (s *Service) ListEnabledModels(ctx context.Context, authority authz.Authority) ([]config.CachedModel, error)
ListEnabledModels returns the models available for selection: enabled models from enabled providers, plus fetched-cache models whose provider is enabled, deduplicated by provider/model and sorted. It performs no provider API calls.
func (*Service) PublicChannels ¶
func (s *Service) PublicChannels(ctx context.Context, authority authz.Authority) ([]PublicChannel, error)
PublicChannels returns the secret-free projection of every configured channel for the user-facing channel list. The transport filters visibility by the caller's agent access and the enabled plugin types; this only supplies the projected rows.
type UpstreamError ¶
type UpstreamError struct{ Err error }
UpstreamError reports a failed call to an external control-plane dependency (e.g. a provider's model-listing endpoint), mapped to 502 by the transport.
func (*UpstreamError) Error ¶
func (e *UpstreamError) Error() string
func (*UpstreamError) Unwrap ¶
func (e *UpstreamError) Unwrap() error
type ValidationError ¶
type ValidationError struct{ Msg string }
ValidationError reports a rejected control-plane input (the legacy 400 path). Msg carries the exact historical client message.
func (*ValidationError) Error ¶
func (e *ValidationError) Error() string