ObjectStackObjectStack

Plugin Runtime

Plugin Runtime protocol schemas

Plugin Runtime Management Protocol

Defines the protocol for dynamic plugin loading, unloading, and discovery

at runtime. Addresses the "Dynamic Loading" gap in the microkernel architecture

by enabling plugins to be loaded and unloaded without restarting the kernel.

Inspired by:

  • OSGi Dynamic Module System (bundle lifecycle)

  • Kubernetes Operator pattern (reconciliation loop)

  • VS Code Extension Host (activation events)

This protocol enables:

  • Runtime load/unload of plugins without kernel restart

  • Plugin discovery from registries and local filesystem

  • Activation events (load plugin only when needed)

  • Safe unload with dependency awareness

Source: packages/spec/src/kernel/plugin-runtime.zod.ts

TypeScript Usage

import { ActivationEventSchema, DynamicLoadRequestSchema, DynamicPluginOperationSchema, DynamicPluginResultSchema, DynamicUnloadRequestSchema, PluginSourceSchema } from '@objectstack/spec/kernel';
import type { ActivationEvent, DynamicLoadRequest, DynamicPluginOperation, DynamicPluginResult, DynamicUnloadRequest, PluginSource } from '@objectstack/spec/kernel';

// Validate data
const result = ActivationEventSchema.parse(data);

ActivationEvent

Lazy activation trigger for a dynamic plugin

Properties

PropertyTypeRequiredDescription
typeEnum<'onCommand' | 'onRoute' | 'onObject' | 'onEvent' | 'onService' | 'onSchedule' | 'onStartup' | 'onMetadataType' | 'onView'>Trigger type for lazy activation
patternstringMatch pattern for the activation trigger

DynamicLoadRequest

Request to dynamically load a plugin at runtime

Properties

PropertyTypeRequiredDescription
pluginIdstringUnique plugin identifier
source{ type: Enum<'npm' | 'local' | 'url' | 'registry' | 'git'>; location: string; version?: string; integrity?: string }Plugin source location for dynamic resolution
activationEvents{ type: Enum<'onCommand' | 'onRoute' | 'onObject' | 'onEvent' | 'onService' | 'onSchedule' | 'onStartup' | 'onMetadataType' | 'onView'>; pattern: string }[]optionalLazy activation triggers; if omitted plugin starts immediately
configRecord<string, any>optionalRuntime configuration overrides
priorityintegerLoading priority (lower is higher)
sandboxbooleanRun in an isolated sandbox
timeoutintegerMaximum time to complete loading in ms

DynamicPluginOperation

Runtime plugin operation type

Allowed Values

  • load
  • unload
  • reload
  • enable
  • disable

DynamicPluginResult

Result of a dynamic plugin operation

Properties

PropertyTypeRequiredDescription
successboolean
operationEnum<'load' | 'unload' | 'reload' | 'enable' | 'disable'>Runtime plugin operation type
pluginIdstring
durationMsintegeroptional
versionstringoptional
error{ code: string; message: string; details?: Record<string, any> }optional
warningsstring[]optional

DynamicUnloadRequest

Request to dynamically unload a plugin at runtime

Properties

PropertyTypeRequiredDescription
pluginIdstringPlugin to unload
strategyEnum<'graceful' | 'forceful' | 'drain'>How to handle in-flight work during unload
timeoutintegerMaximum time to complete unloading in ms
cleanupCachebooleanRemove cached code and assets after unload
dependentActionEnum<'cascade' | 'warn' | 'block'>How to handle plugins that depend on this one

PluginSource

Plugin source location for dynamic resolution

Properties

PropertyTypeRequiredDescription
typeEnum<'npm' | 'local' | 'url' | 'registry' | 'git'>Plugin source type
locationstringPackage name, file path, URL, or git repository
versionstringoptionalSemver version range (e.g., "^1.0.0")
integritystringoptionalSubresource Integrity hash (e.g., "sha384-...")

On this page