bootstrap

package
v0.1.12 Latest Latest
Warning

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

Go to latest
Published: Oct 9, 2026 License: MIT Imports: 40 Imported by: 0

Documentation

Overview

Package bootstrap loads configuration and assembles the application: it resolves secret placeholders, opens the database provider, converts config entities to the core entity model, and wires the registry, authorizer, cost gate, engine, and tools. It is the only place that imports gopkg.in/yaml.v3 and x/providers.

Index

Constants

This section is empty.

Variables

View Source
var ErrPlaintextSecret = errors.New("store payload must not contain plaintext secrets")

ErrPlaintextSecret rejects store payloads that would persist credentials.

View Source
var ErrReloadBacklog = errors.New("bootstrap: earlier configurations are still draining; try again")

ErrReloadBacklog is returned by a reload while maxRetiring replaced snapshots still serve requests: each holds its own engine and prepared statements, so reloads wait for them to drain rather than pile them up.

View Source
var ErrRestartRequired = errors.New("config change requires restart")

ErrRestartRequired marks a configuration change that cannot be applied by hot reload or publish without restarting the server.

View Source
var ErrRuntimeClosed = errors.New("bootstrap: runtime closed")

ErrRuntimeClosed is returned when a closed runtime is used.

ErrUnsupportedDriver is returned for a driver with no provider yet.

Functions

func CapabilityWarnings added in v0.1.11

func CapabilityWarnings(cfg *config.Config, capabilities EntityCapabilities) []string

CapabilityWarnings lists actions cfg grants that the routed connection cannot run, in a stable order.

func CheckHotReload added in v0.1.11

func CheckHotReload(old, next *config.Config) error

CheckHotReload reports whether next can replace old without a restart. File reload, store reload and store publish share this rule: the transport, the address, and serving TLS or not need a restart; the rest, authentication and the listed tools included, follows a reload.

func CheckPublishable added in v0.1.11

func CheckPublishable(current, target revision.Revision, restartRequired bool) error

CheckPublishable verifies that target loads under the store rules and, when current is published (ID != 0), that switching to target needs no restart unless restartRequired is set. A current revision that no longer loads can only be replaced with restartRequired.

func Load

func Load(path string) (*config.Config, error)

Load reads and validates a YAML config file.

func LoadBytes added in v0.1.11

func LoadBytes(data []byte) (*config.Config, error)

LoadBytes decodes, defaults and validates YAML configuration bytes and checks that every driver is registered, like Load does for a file.

func LoadRevision added in v0.1.11

func LoadRevision(rev revision.Revision) (*config.Config, error)

LoadRevision verifies a revision's content hash and decodes its payload under the store-mode secret rule.

func OfflineAuthorizer added in v0.1.11

func OfflineAuthorizer(cfg *config.Config) (rbac.Authorizer, error)

OfflineAuthorizer compiles cfg's entities, roles and users into an authorizer without connecting to any database, for policy simulation.

func RedactDSN

func RedactDSN(driver, dsn string) string

RedactDSN returns dsn with every password the driver would read replaced by ***, for logging and display.

func RestartChanges added in v0.1.11

func RestartChanges(old, next *config.Config) []string

RestartChanges lists the changes from old to next that need a restart.

func UserPrincipal added in v0.1.11

func UserPrincipal(user string) string

UserPrincipal returns the principal key of a configured user.

func ValidateFile

func ValidateFile(path string, resolver SecretResolver) error

ValidateFile parses, defaults, validates, and resolves secrets without opening database connections.

func ValidateStorePayload added in v0.1.11

func ValidateStorePayload(cfg *config.Config) error

ValidateStorePayload enforces the store-mode secret rule: every non-empty DSN password must come from a ${...} placeholder and server.auth.token must be empty (configured users keep only token hashes).

Types

type App

type App struct {
	Provider Provider
	// Providers holds each datasource's read connection, which also serves
	// introspection and EXPLAIN; Connections holds every connection.
	Providers   map[string]Provider
	Connections Connections
	Prepared    map[string]*store.PreparedDB
	Sources     map[string]tool.DataSource
	Dialect     dialect.Dialect
	Registry    *entity.Registry
	Authorizer  rbac.Authorizer
	Masker      mask.Masker
	Gate        cost.Gate
	Engine      *engine.Engine
	Tools       *tool.Registry
	ToolFlags   config.ToolFlags
	DefaultRole string
	DefaultUser string
	// Users maps an enabled user name to its identity; UserTokens maps a
	// tokenHash to the user name. Both follow the snapshot on reload.
	Users        map[string]UserIdentity
	UserTokens   map[string]string
	Limits       tool.Limits
	Auditor      audit.Auditor
	Hooks        *hook.Hooks
	Cache        cache.Cache[[]map[string]any]
	Feedback     cost.FeedbackStore
	Analyze      cost.AnalyzePolicy
	Budget       *budget.MemoryManager
	Transactions *tool.TransactionManager
	Writes       *tool.WriteTracker
	TxBeginners  map[string]store.TxBeginner
	// WriteTargets are what a write through each entity invalidates.
	WriteTargets *tool.WriteTargets
	// contains filtered or unexported fields
}

App is the assembled application, ready to serve.

func Assemble

func Assemble(cfg *config.Config) (*App, error)

Assemble opens the provider and wires the application from cfg, using the default EnvFileResolver for secret placeholders.

func AssembleWithConnections added in v0.1.11

func AssembleWithConnections(cfg *config.Config, connections Connections) (*App, error)

AssembleWithConnections wires opened connections. Ownership transfers to the returned App on success. On failure the connections stay with the caller and every resource acquired here is released: configuration is checked before any resource is acquired. Each datasource's read connection serves introspection and EXPLAIN.

func AssembleWithProvider

func AssembleWithProvider(cfg *config.Config, prov Provider) (*App, error)

AssembleWithProvider wires the application using an injected provider (for testing with fakes).

func AssembleWithProviders

func AssembleWithProviders(cfg *config.Config, providers map[string]Provider) (*App, error)

AssembleWithProviders wires one provider per datasource, serving every connection the datasource configures. It is intended for tests and embedders; ownership transfers to the returned App on success.

func AssembleWithResolver

func AssembleWithResolver(cfg *config.Config, r SecretResolver) (*App, error)

AssembleWithResolver resolves secrets with the given resolver, opens the provider, and wires the application. Use a custom resolver to integrate secret managers (Vault, AWS Secrets Manager, etc.) without coupling core to any specific backend.

func (*App) Capabilities added in v0.1.11

func (a *App) Capabilities() EntityCapabilities

Capabilities returns what the routed connections may do per entity action, as the databases reported after the App was assembled; nil (unknown) while they are being assessed.

func (*App) Close

func (a *App) Close() error

Close preserves the original unbounded close contract. Callers that need a shutdown deadline should use CloseContext.

func (*App) CloseContext

func (a *App) CloseContext(ctx context.Context) error

CloseContext stops engine admission and drains all execution before rolling back transactions and releasing audit/provider resources.

func (*App) Config added in v0.1.12

func (a *App) Config() *config.Config

Config returns the configuration the App was assembled from.

func (*App) OpenScan added in v0.1.12

func (a *App) OpenScan(ctx context.Context, database config.DatabaseConfig) (p Provider, ok bool, err error)

OpenScan opens a connection of its own to the read connection of database, as given, for a schema scan: it takes no serving connection and does not hold the snapshot, so neither requests nor reloads wait for the scan, and it reads the database the caller names even before this App is replaced by one configured so. The caller closes it; ctx bounds opening it. ok is false when the App was assembled from connections it was handed and cannot open more.

func (*App) Ping added in v0.1.6

func (a *App) Ping(ctx context.Context) error

Ping verifies every configured database is reachable. It backs the /readyz/db readiness probe and stays off the tool execution path: it uses the provider's native connection ping when exposed and falls back to a trivial query otherwise.

func (*App) ToolContext

func (a *App) ToolContext(role string) tool.Context

ToolContext builds a per-request tool.Context for the given role.

func (*App) ToolContextForSubject

func (a *App) ToolContextForSubject(role string, subject map[string]any) tool.Context

ToolContextForSubject builds a per-request tool.Context for a role plus subject attributes (referenced by row-level ${subject.x} policies).

func (*App) UserByName added in v0.1.11

func (a *App) UserByName(name string) (UserIdentity, bool)

UserByName returns an enabled user by name.

func (*App) UserByTokenHash added in v0.1.11

func (a *App) UserByTokenHash(hash string) (UserIdentity, bool)

UserByTokenHash returns the enabled user whose tokenHash matches.

func (*App) WaitCapabilities added in v0.1.12

func (a *App) WaitCapabilities(ctx context.Context) (EntityCapabilities, error)

WaitCapabilities waits for the assessment of capabilities, or for ctx.

type Capability added in v0.1.11

type Capability struct {
	Privilege  introspect.Privilege
	Connection string
	// Columns lists the columns granted at column level when the table-level
	// privilege is not granted.
	Columns []string
	Reason  string
}

Capability says whether the connection an entity action routes to may run it, as far as the database reports (I-3). It informs administrators; the database decides each statement.

type Connections added in v0.1.11

type Connections map[string]map[string]Provider

Connections are opened providers by datasource and connection name.

type EntityCapabilities added in v0.1.11

type EntityCapabilities map[string]map[entity.Action]Capability

EntityCapabilities are capabilities by entity and action.

type EnvFileResolver

type EnvFileResolver struct {
	AllowedRoots []string
}

EnvFileResolver resolves ${ENV} (environment variables) and ${file:/path} (file contents, e.g. Kubernetes Secret volume mounts).

func (EnvFileResolver) Resolve

func (r EnvFileResolver) Resolve(s string) (string, error)

Resolve implements SecretResolver.

type Provider

type Provider = coreprovider.Provider

Provider aggregates the core interfaces a database adapter must satisfy.

type Runtime

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

Runtime owns the atomically replaceable App snapshot used by serving handlers. A successful reload publishes the new App at once, so requests never wait for a reload, and drains and closes the old one in the background; a failed build leaves the current App untouched.

func NewRuntimeWithBuilder

func NewRuntimeWithBuilder(app *App, build func(string) (*App, error)) *Runtime

NewRuntimeWithBuilder creates a runtime with an injected reload builder. It is useful for embedders and tests that assemble providers themselves.

func (*Runtime) Acquire

func (r *Runtime) Acquire() (*App, func(), error)

Acquire leases the current snapshot until the returned release function is called. It retries when racing with retirement.

func (*Runtime) AppliedRevision added in v0.1.11

func (r *Runtime) AppliedRevision() int64

AppliedRevision returns the store revision the runtime serves as tracked by WatchStore, or 0 before WatchStore starts.

func (*Runtime) Close

func (r *Runtime) Close() error

Close stops new acquisitions, drains leases, and closes the current App and the ones reloads replaced.

func (*Runtime) Current

func (r *Runtime) Current() *App

Current returns the currently published App, or nil after Close. Handlers that execute work must use Acquire so the App cannot close during the call.

func (*Runtime) DatabasesReady added in v0.1.6

func (r *Runtime) DatabasesReady(ctx context.Context) error

DatabasesReady pings every database of the current snapshot. It backs the /readyz/db readiness probe.

func (*Runtime) OnPublish added in v0.1.12

func (r *Runtime) OnPublish(fn func(*App))

OnPublish calls fn with the current App and then with every App a reload publishes, as it is published. Registering and the first call happen between reloads, so fn misses none. Transports use it to follow the configuration: the tools they list, how they authenticate.

func (*Runtime) OnRevokedPrincipals added in v0.1.11

func (r *Runtime) OnRevokedPrincipals(fn func([]string) []string)

OnRevokedPrincipals registers fn to receive the principal keys of users that a successful reload removed or disabled, as the new snapshot is published. Transports use it to drop those users' sessions and roll back their transactions; fn returns the sessions it dropped. Once requests on the old snapshot finish, transactions they opened in those sessions are rolled back too. Sessions are named by their IDs, never reused, so a user enabled again keeps the sessions it opens meanwhile.

func (*Runtime) Reload

func (r *Runtime) Reload(path string) error

Reload performs parse/default/validate/secret-resolution/assembly before atomically publishing the new App. Build failure preserves the old snapshot.

func (*Runtime) ReloadWith added in v0.1.11

func (r *Runtime) ReloadWith(build func() (*App, error)) error

ReloadWith publishes the App returned by build, with the same budget, transaction and drain handling as Reload.

func (*Runtime) RollbackSession

func (r *Runtime) RollbackSession(session string)

RollbackSession rolls back transactions associated with a disconnected MCP session when the transport exposes a stable non-empty session ID.

func (*Runtime) SnapshotReady added in v0.1.6

func (r *Runtime) SnapshotReady(context.Context) error

SnapshotReady reports whether a configuration snapshot is currently published and servable. It backs the /readyz/snapshot readiness probe.

func (*Runtime) Stale added in v0.1.11

func (r *Runtime) Stale() (StaleState, bool)

Stale returns the unapplied published revision, if any.

func (*Runtime) UserByName added in v0.1.11

func (r *Runtime) UserByName(name string) (UserIdentity, bool)

UserByName resolves an enabled user against the current snapshot.

func (*Runtime) UserByTokenHash added in v0.1.11

func (r *Runtime) UserByTokenHash(hash string) (UserIdentity, bool)

UserByTokenHash resolves a tokenHash against the current snapshot.

func (*Runtime) Watch

func (r *Runtime) Watch(ctx context.Context, path string, interval time.Duration, onError func(error)) error

Watch polls path for content changes and reloads it. Reload errors are reported through onError and do not stop the watcher or replace the old App.

func (*Runtime) WatchStore added in v0.1.11

func (r *Runtime) WatchStore(
	ctx context.Context,
	store revision.Store,
	current int64,
	interval time.Duration,
	build func(revision.Revision) (*App, error),
	onError func(error),
) error

WatchStore polls store for a newly published revision and reloads it with build. current is the revision the runtime already serves. Failures keep the current snapshot (fail-static) and are recorded in Stale; a later successful reload clears it.

type SecretResolver

type SecretResolver interface {
	Resolve(s string) (string, error)
}

SecretResolver resolves ${...} placeholders in a string (e.g. a DSN). EnvFileResolver is the built-in implementation; custom implementations can back this by Vault, AWS Secrets Manager, GCP Secret Manager, etc., without coupling core to any specific backend.

type Shared added in v0.1.12

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

Shared holds what the Apps of one process share across reloads, so the old and the new configuration, serving side by side while the old one drains, act as one process: the read cache, which a write through either invalidates; the IO quota, which bounds both together; and the database connections, reused while their settings stay the same.

func NewShared added in v0.1.12

func NewShared() *Shared

NewShared returns empty shared services.

func (*Shared) Assemble added in v0.1.12

func (s *Shared) Assemble(cfg *config.Config) (*App, error)

Assemble opens (or reuses) the connections of cfg and wires an App on the shared services, resolving secrets like Assemble.

type StaleState added in v0.1.11

type StaleState struct {
	RevisionID int64
	Err        string
	// RestartRequired reports that the revision only applies after a restart.
	RestartRequired bool
}

StaleState describes a published store revision the runtime has not applied, either because building it failed or because it needs a restart.

type UserIdentity added in v0.1.11

type UserIdentity struct {
	Principal string
	Roles     []string
	Subject   map[string]any
}

UserIdentity is the runtime view of an enabled user.

Jump to

Keyboard shortcuts

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