liquidrazor / micro-kernel
Lifecycle authority for isolated executable work inside the LiquidRazor Framework.
Requires
- php: ^8.3
- ext-pcntl: *
- ext-posix: *
- liquidrazor/diregistry: ^0.1
- liquidrazor/event-manager: ^0.1
- liquidrazor/kernel-state-events: ^0.1
- liquidrazor/posix-runtime: ^0.1
- liquidrazor/process-events: ^0.1
Requires (Dev)
- phpunit/phpunit: ^12.5
README
The LiquidRazor MicroKernel is the lifecycle authority for isolated executable work inside the LiquidRazor Framework.
It is transport-agnostic, but not runtime-naive.
The MicroKernel does not care whether work originates from HTTP, CLI, gRPC, queues, cron jobs, daemons, or another runtime adapter. It does care that every unit of work follows a predictable lifecycle, receives the correct runtime scope, emits the correct lifecycle events, and is supervised consistently.
The goal is simple: transport kernels plug into one execution model instead of each transport inventing its own process-control circus.
Table of Contents
- Purpose
- Doctrine
- Goals
- Non-Goals
- Package Boundary
- Relationship to Other LiquidRazor Packages
- Lifecycle Model
- Worker Execution Model
- Runtime Scope Model
- Event Model
- Process Supervision
- Transport Kernel Boundary
- Failure Model
- Directory Structure
- Design Constraints
- Versioning
- License
Purpose
The MicroKernel provides the framework-level execution lifecycle for work that must run inside an isolated runtime context.
It owns the generic lifecycle required by higher-level runtime kernels:
- booting the kernel infrastructure;
- compiling immutable framework metadata;
- loading the dependency registry;
- warming long-lived parent runtime state;
- entering a ready state;
- spawning or attaching isolated workers;
- creating runtime scopes for work execution;
- supervising worker state;
- emitting lifecycle events;
- handling shutdown semantics.
The MicroKernel is intentionally below HTTP, CLI, gRPC, queue, and other transport-specific kernels. Those kernels should describe the source and shape of the work. The MicroKernel owns the execution lifecycle around that work.
Doctrine
The MicroKernel is transport-agnostic but not runtime-naive.
It does not know or care whether a request came from a web server, a terminal command, a message broker, or an RPC call. It does know that the work must enter a consistent lifecycle and that runtime state must be isolated correctly.
Transport kernels must plug into the MicroKernel lifecycle instead of implementing independent process-control behavior.
POSIX signal handling, where available, is the authoritative mechanism for forked worker supervision. PID checks are fallback validation only.
Goals
The MicroKernel exists to provide:
- one framework-owned lifecycle for isolated executable work;
- clean separation between transport adapters and runtime execution;
- predictable kernel state transitions;
- safe long-lived parent process behavior;
- isolated mutable state per worker, child, request, command, or job;
- explicit worker identity and supervision contracts;
- lifecycle events for kernel state and process execution;
- integration points for POSIX-based worker supervision;
- a stable foundation for HTTP, CLI, gRPC, queue, and daemon kernels.
Non-Goals
The MicroKernel does not provide:
- an HTTP router;
- a controller system;
- a CLI command framework;
- a gRPC server;
- a queue consumer implementation;
- a full worker pool manager;
- a web server;
- a replacement for RoadRunner, FrankenPHP, Swoole, or PHP-FPM;
- application business logic;
- transport-specific request or response abstractions.
The MicroKernel may support worker spawning and supervision contracts, but it is not itself a complete process manager or queue runtime.
Package Boundary
Expected package identity:
GitHub: https://github.com/LiquidRazor/MicroKernel
Packagist: liquidrazor/micro-kernel
The package should expose contracts and reusable lifecycle components that other LiquidRazor runtime kernels can depend on.
It should remain small, strict, and boring in the good sense. The exciting bugs can live somewhere else, preferably nowhere.
Relationship to Other LiquidRazor Packages
The MicroKernel depends conceptually on the existing LiquidRazor foundation packages.
EventManager
Package:
liquidrazor/event-manager
The EventManager is pure event infrastructure.
The MicroKernel must use it to dispatch lifecycle events. It must not redefine event infrastructure locally.
KernelStateEvents
Package:
liquidrazor/kernel-state-events
KernelStateEvents provides immutable framework-owned events for kernel lifecycle transitions.
The MicroKernel emits these events during boot, compile, warm, ready, and shutdown phases.
ProcessEvents
Package:
liquidrazor/process-events
ProcessEvents provides immutable process/runtime events for worker and external-call lifecycles.
The MicroKernel currently emits process events for worker spawning, starting, finishing, and crashing.
Worker timeout and cancellation remain part of the worker lifecycle model, but no corresponding upstream process event classes are emitted until that event surface exists.
POSIXRuntime
Package:
liquidrazor/posix-runtime
POSIXRuntime provides POSIX-oriented runtime capabilities used by the MicroKernel when process control is required.
The MicroKernel should rely on POSIXRuntime for signal-aware process supervision instead of implementing raw process-control behavior directly in random corners of the codebase, because that is how civilizations collapse.
DIRegistry
Package:
liquidrazor/diregistry
DIRegistry is the dependency registry and instantiation system.
The MicroKernel should integrate with DIRegistry for compiled dependency metadata and runtime scope creation. Long-lived parent processes must retain only immutable services and structural metadata. Mutable services must be scoped, transient, or otherwise isolated per unit of work.
FileLocator, ClassLocator, RegistryLoader, ConfigLoader
Packages:
liquidrazor/file-locator
liquidrazor/class-locator
liquidrazor/registry-loader
liquidrazor/config-loader
These packages support discovery, configuration loading, and registry construction outside the MicroKernel itself.
The MicroKernel should consume compiled results where possible and avoid becoming a configuration parser, class scanner, or service discovery engine.
Lifecycle Model
The MicroKernel lifecycle is divided into stable phases.
Booting
Booted
Compiling
Compiled
ContainerLoading
ContainerLoaded
Warming
Warmed
Ready
WorkerSpawned
WorkerStarted
WorkerFinished | WorkerCrashed | WorkerTimedOut | WorkerCancelled
ShuttingDown
Shutdown
Kernel lifecycle emission uses the current KernelStateEvents catalog through Shutdown.
Worker lifecycle emission currently uses ProcessEvents for spawned, started, finished, and crashed states.
Boot Phase
The boot phase initializes the minimal kernel infrastructure required to continue safely.
This phase should avoid loading mutable runtime state. Boot should establish the kernel identity, environment, runtime mode, and minimal event infrastructure.
Compile Phase
The compile phase resolves immutable framework metadata.
This may include prepared registry data, discovered structural metadata, event catalogs, configuration snapshots, and other framework-level information that can safely survive in a long-lived parent process.
Compile output must be treated as immutable.
Container Loading Phase
The container loading phase loads or creates the dependency registry used by the runtime.
The parent process may keep immutable registry metadata and safe readonly services. Mutable state must not leak into the warmed parent runtime.
Warm Phase
The warm phase prepares the parent runtime for efficient repeated execution.
Warming may preload metadata, readonly services, immutable indexes, event catalogs, and other safe structures.
Warming must not create per-request, per-command, or per-job mutable state.
Ready Phase
The ready phase indicates that the MicroKernel can accept executable work from transport kernels.
At this point, transport kernels may pass work descriptors into the MicroKernel execution model.
Worker Execution Model
A worker is an isolated execution context for one unit of work.
Depending on the runtime, a worker may represent:
- a forked child process;
- an attached child process;
- a scoped in-process execution context;
- a supervised command execution;
- a queue job execution;
- a long-running daemon task iteration.
The MicroKernel owns the generic worker lifecycle. Transport kernels own the transport-specific interpretation of the work.
A worker must have:
- a stable worker identity;
- a runtime scope identity;
- a parent kernel identity;
- a lifecycle state;
- supervision metadata where applicable;
- failure metadata where applicable.
Runtime Scope Model
The MicroKernel must enforce separation between long-lived parent state and mutable runtime state.
Parent runtime may keep:
- immutable metadata;
- readonly services;
- compiled registry data;
- structural indexes;
- locked event catalogs;
- static configuration snapshots.
Worker runtime may contain:
- request state;
- command state;
- job state;
- scoped services;
- transient services;
- per-execution buffers;
- mutable context objects;
- failure and retry metadata.
No long-lived parent service may depend on shorter-lived mutable services.
That rule is not decorative. It is the difference between a framework and a slow-motion memory leak wearing a tie.
Event Model
The MicroKernel emits events but does not define the event system.
Event responsibilities are split as follows:
- EventManager provides dispatching and listener infrastructure.
- KernelStateEvents provides framework-owned kernel lifecycle events.
- ProcessEvents provides process and worker lifecycle events.
- The MicroKernel coordinates lifecycle transitions and emits the appropriate events.
Current emitted worker event coverage is:
WorkerSpawnedEventWorkerStartedEventWorkerFinishedEventWorkerCrashedEvent
Timeout and cancellation remain explicit worker states, but they do not emit upstream process events yet.
Kernel state event catalogs are framework-owned and should be immutable after load and registration.
Process event catalogs are runtime-extensible where appropriate and may support custom developer-defined process events before runtime locking.
Process Supervision
The MicroKernel must support supervision contracts for workers.
Where POSIX is available, signal handling is the authoritative supervision mechanism for forked workers.
PID checks are fallback validation only. They must not be treated as the primary source of process truth when signal-aware supervision is available.
The MicroKernel should support supervision concepts such as:
- worker spawned;
- worker started;
- worker finished;
- worker crashed;
- worker timed out;
- worker cancelled;
- worker shutdown requested;
- worker force-kill requested;
- worker cleanup required.
Actual low-level POSIX behavior belongs in POSIXRuntime.
The MicroKernel should depend on clear runtime contracts rather than scattering process-control code across lifecycle orchestration.
The current POSIX supervision boundary maps runtime capability status, process outcome state, cleanup requirements, and shutdown propagation requirements through POSIXRuntime contracts.
Transport Kernel Boundary
Transport kernels adapt specific sources of work into MicroKernel execution.
Examples:
- an HTTP kernel adapts HTTP requests;
- a CLI kernel adapts console commands;
- a gRPC kernel adapts RPC calls;
- a queue kernel adapts broker messages;
- a daemon kernel adapts repeated scheduled work.
Transport kernels may define transport-specific request, response, command, message, or stream abstractions.
They must not own the generic lifecycle for worker identity, runtime scopes, supervision contracts, parent shutdown, or process events.
Those belong to the MicroKernel.
Failure Model
The MicroKernel must treat failures as lifecycle states, not random exceptions flying around like angry birds in a server room.
Failures should be classified where possible:
- boot failure;
- compile failure;
- container loading failure;
- warmup failure;
- worker spawn failure;
- worker runtime failure;
- worker crash;
- worker timeout;
- worker cancellation;
- shutdown failure;
- cleanup failure.
Failure information should be represented by typed metadata objects where useful, especially for process and worker events.
The MicroKernel should make failure states observable through events and explicit result objects.
Directory Structure
The package follows the standard LiquidRazor library structure:
include/
lib/
src/
tests/
docs/
include/
Contains contracts, value objects, enums, definitions, and exceptions.
This layer must not depend on lib/ or src/.
lib/
Contains reusable implementation logic.
This layer may depend on include/, but not on src/.
src/
Contains runtime integration and package wiring.
This layer may depend on include/ and lib/.
tests/
Contains test coverage for contracts, lifecycle orchestration, state transitions, runtime scopes, supervision behavior, and failure handling.
docs/
Contains public documentation and design notes intended for users and contributors.
Design Constraints
The MicroKernel must follow these constraints:
- PHP 8.3+ minimum unless raised by the framework baseline;
- strict types everywhere;
- no framework-specific transport assumptions;
- no local redefinition of EventManager contracts;
- no local redefinition of KernelStateEvents or ProcessEvents contracts;
- no raw process-control sprawl when POSIXRuntime provides the relevant abstraction;
- immutable parent runtime state only;
- mutable state must be scoped to workers or execution contexts;
- explicit lifecycle transitions;
- typed identities for kernel, worker, and runtime scope concepts;
- typed metadata for meaningful failure and supervision events;
- no hidden global state;
- no transport-specific request or response model inside the MicroKernel.
Versioning
Initial development begins at:
v0.1.0
Breaking changes are expected while the lifecycle contracts stabilize.
License
MIT