Documentation
¶
Overview ¶
Package kernel is the public contract of Lesstruct v1 ("everything is a module").
Kernel owns the Module lifecycle, the Principal identity shape, the module registry, and the database driver/dialect contracts. It imports nothing from Lesstruct modules or internals, so dependencies always point one way: modules import kernel, the composition root imports everything.
Versioning: the kernel is an independent Go module tagged kernel/vX.Y.Z. Semver rules, stability classes, and the deprecation flow live in docs/kernel-versioning.md. The one rule to internalize: adding a method to an exported interface is a breaking change — prefer new narrow interfaces over widening existing ones.
Terminology: "modules" are compile-time Go modules (Tier 1). "Plugins" are the sandboxed WASM extensions (Tier 2) and live outside this package.
Index ¶
- Variables
- func Capabilities[T any](r *Registry) []T
- func ContextWithPrincipal(ctx context.Context, principal Principal) context.Context
- type AdminExtensionManifest
- type AdminExtensionProvider
- type AdminMenuEntry
- type CapabilityResolver
- type ContentTypeProvider
- type DroppedModule
- type Host
- type Kernel
- type Logger
- type Migrator
- type Module
- type PostTypeDef
- type Principal
- type PruneResult
- type PublicRouteProvider
- type Registry
- func (r *Registry) Get(name string) (Module, bool)
- func (r *Registry) InitAll(kernel Kernel) error
- func (r *Registry) InitOrder() []string
- func (r *Registry) Initialized() bool
- func (r *Registry) Names() []string
- func (r *Registry) Register(module Module) error
- func (r *Registry) ShutdownAll() error
- type RoleProvider
- type RouteProvider
- type ThemeProvider
Constants ¶
This section is empty.
Variables ¶
var ( ErrDuplicateModule = errors.New("kernel: duplicate module") ErrMissingDependency = errors.New("kernel: missing module dependency") ErrCircularDependency = errors.New("kernel: circular module dependency") ErrNilKernel = errors.New("kernel: host cannot be nil") ErrNilModule = errors.New("kernel: module cannot be nil") )
var ErrInvalidPrincipalID = errors.New("kernel: invalid principal ID")
ErrInvalidPrincipalID marks a principal whose ID is not a decimal user ID.
Functions ¶
func Capabilities ¶
Capabilities collects every registered module implementing capability T in registry name order. It is the discovery mechanism modules use instead of a service locator.
Types ¶
type AdminExtensionManifest ¶
type AdminExtensionManifest struct {
MenuEntries []AdminMenuEntry
SettingsSections []string
EditorExtensions []string
}
AdminExtensionManifest is the declarative UI a feature module contributes to the admin shell: navigation, settings sections, and editor extensions. One shell renders everything; modules never ship their own mini-SPA.
func (AdminExtensionManifest) Validate ¶
func (m AdminExtensionManifest) Validate() error
Validate ensures a manifest's entries are well-formed: menu entries need a label, an absolute path, and no duplicate paths. It mirrors the shell's own checks so module authors catch malformed manifests in unit tests (see kernel/conformance CheckAdminExtension for the third-party fixture).
type AdminExtensionProvider ¶
type AdminExtensionProvider interface {
Module
AdminManifest() AdminExtensionManifest
}
AdminExtensionProvider contributes UI to the admin shell via manifest.
type AdminMenuEntry ¶
AdminMenuEntry is one navigation item contributed to the admin shell.
type CapabilityResolver ¶
CapabilityResolver maps a principal plus a capability name (for example "content.publish") to an allow/deny decision.
Implemented by the users module. The kernel never resolves roles itself.
type ContentTypeProvider ¶
type ContentTypeProvider interface {
Module
PostTypes() []PostTypeDef
}
ContentTypeProvider registers content types (post, page, product, ...).
type DroppedModule ¶
type DroppedModule struct {
// Name is the dropped module's registry key.
Name string
// Direct is true when the module itself was named in disabled, false
// when it cascaded from a disabled requirement.
Direct bool
// Cause names the disabled module that forced the drop: the module
// itself when Direct, otherwise the unavailable requirement.
Cause string
}
DroppedModule names one module Prune removed from the candidate list.
type Host ¶
type Host struct {
// contains filtered or unexported fields
}
Host is the default Kernel implementation handed to Module.Init.
type Logger ¶
Logger is the printf-style logging contract modules use.
Core adapts *util.Logger to it; tests and fixtures may supply any sink. Messages use fmt-style verbs, matching the util.Logger convention.
type Migrator ¶
Migrator ships namespaced migrations as an embedded filesystem.
Layout convention: {sqlite,postgresql,mysql}/NNN_name.{up,down}.sql. The core migration runner selects the subdir via Driver.MigrationDir.
type Module ¶
type Module interface {
Name() string
Version() string
Requires() []string
Optional() []string
Init(kernel Kernel) error
Shutdown() error
}
Module is the only interface every Lesstruct module must implement.
Name is the stable registry key ("users", "comments", "site-ssr"). Requires lists hard dependencies resolved topologically at startup; Optional lists soft dependencies the module degrades without. Init wires the module (routes, subscriptions, services); Shutdown releases it.
type PostTypeDef ¶
PostTypeDef is the minimal post-type registration the kernel understands. Richer definitions (fields, templates) live in the posttypes module. Protected marks slugs reserved by built-in modules (post, page, media, comment): the kernel index records them so later phases can refuse overrides, and config entries may not hide them.
type Principal ¶
Principal is the minimal identity every auth module injects into requests.
The kernel owns this shape — never a concrete user type — so identity stays a module concern (users/auth) while route protection stays declarative.
func PrincipalFromContext ¶
PrincipalFromContext reads the principal back. ok is false on anonymous requests, where no auth module ran.
func (Principal) IsAnonymous ¶
IsAnonymous reports whether no identity module populated the principal.
type PruneResult ¶
type PruneResult struct {
Kept []Module
Dropped []DroppedModule
}
PruneResult is the outcome of Prune: the modules to register plus every dropped module with its reason.
func Prune ¶
func Prune(candidates []Module, disabled []string) PruneResult
Prune removes disabled modules and their transitive dependents from the candidate list. It is a pure function over Requires edges: no registry mutation, no I/O, deterministic output in candidate order.
A module named in disabled drops as Direct. Any other module whose Requires names a dropped or disabled module drops as a cascade, naming the unavailable requirement as Cause. Modules whose hard dependency is merely absent (not disabled) are KEPT: the registry still fails fast on those at InitAll, unchanged. Nil candidates are skipped.
type PublicRouteProvider ¶
PublicRouteProvider mounts HTTP routes onto the shared Chi router. Core passes the public router (no auth chain), so everything mounted here is anonymous. Prefer RouteProvider unless the endpoint is genuinely public.
The method is deliberately named differently from RouteProvider's so one module can serve both surfaces and core can discover each independently: a single RegisterRoutes method would satisfy both interfaces at once and mount the same routes twice.
type Registry ¶
type Registry struct {
// contains filtered or unexported fields
}
Registry is the module graph: it stores modules, resolves their Requires edges into a deterministic init order, and runs lifecycle transitions. Register order never matters; InitAll always topologically sorts.
func (*Registry) InitAll ¶
InitAll resolves the dependency graph and calls Init on every module in topological order. A hard Requires edge to an unregistered module fails fast; an Optional edge to one is silently skipped. The first Init error aborts the transition and leaves Initialized false; already-initialized modules are NOT rolled back — the caller owns that (at startup the process exits, so there is nothing to roll back to). InitAll is a single-shot startup transition, not safe for concurrent use.
func (*Registry) InitOrder ¶
InitOrder returns the topological init order from the last InitAll, or nil when InitAll has not run.
func (*Registry) Initialized ¶
Initialized reports whether InitAll completed successfully.
func (*Registry) ShutdownAll ¶
ShutdownAll calls Shutdown in reverse init order, collecting every error with errors.Join. Modules never initialized are skipped.
type RoleProvider ¶
RoleProvider contributes capability strings to the permission registry.
type RouteProvider ¶
RouteProvider mounts HTTP routes onto the shared Chi router. Core passes the protected router (auth middleware pre-chained), so everything mounted here requires authentication. For anonymous surfaces, implement PublicRouteProvider instead.
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
Package capability defines the Published Language of authorization: the capability names every module checks and the users module resolves.
|
Package capability defines the Published Language of authorization: the capability names every module checks and the users module resolves. |
|
Package conformance ships embeddable test suites that third-party module authors run against their kernel-contract implementations.
|
Package conformance ships embeddable test suites that third-party module authors run against their kernel-contract implementations. |
|
Package httpx is the kernel's HTTP response envelope: the one wire format every module writes.
|
Package httpx is the kernel's HTTP response envelope: the one wire format every module writes. |
|
Package posttype is the kernel's content-type discovery index.
|
Package posttype is the kernel's content-type discovery index. |
|
Package storage defines the file-storage contract for media-like resources.
|
Package storage defines the file-storage contract for media-like resources. |