liquidrazor / http-kernel
Concrete HTTP transport kernel for the LiquidRazor Framework.
Requires
- php: ^8.3
- liquidrazor/diregistry: ^0.1
- liquidrazor/event-manager: ^0.1
- liquidrazor/http-contracts: ^0.1.1
- liquidrazor/micro-kernel: ^0.1
- liquidrazor/transport-contracts: ^0.1
Requires (Dev)
- phpunit/phpunit: ^12.5
README
liquidrazor/http-kernel is the concrete HTTP transport kernel for the LiquidRazor Framework.
It adapts HTTP request/response semantics into the LiquidRazor MicroKernel isolated execution lifecycle.
The package exists to connect:
native HTTP runtime input
-> HTTP request normalization
-> HTTP transport input
-> MicroKernel isolated execution
-> HTTP response finalization
-> native HTTP runtime output
It is the first full transport kernel in the LiquidRazor stack and the first package where the HTTP contracts, transport contracts, dependency registry, event infrastructure, process supervision model, and micro-kernel lifecycle are expected to work together.
Table of Contents
- Purpose
- Architectural Position
- Doctrine
- Goals
- Non-Goals
- Package Boundary
- Relationship to Other LiquidRazor Packages
- Execution Model
- Warm Parent and Forked Child Boundary
- HTTP Request Lifecycle
- HTTP Response Lifecycle
- Transport Integration
- Runtime Scope Model
- Event Model
- Adapter and Emitter Model
- Dependency Model
- Failure Model
- Public Docs
- Directory Structure
- Version 0.1.0 Scope
- Design Constraints
- License
Purpose
HTTPKernel provides the HTTP-specific runtime layer above the LiquidRazor MicroKernel.
The MicroKernel owns isolated executable work. HTTPKernel owns the HTTP interpretation of that work.
HTTPKernel is responsible for:
- accepting native HTTP input through adapters;
- normalizing HTTP input into
HttpRequestInterface; - creating HTTP transport input and HTTP exchange state;
- entering the MicroKernel isolated execution lifecycle;
- creating request-scoped runtime context for child execution;
- invoking the configured HTTP application handler boundary;
- validating and finalizing
HttpResponseInterfaceoutput; - wrapping the response in HTTP transport output;
- handing finalized output to an emitter boundary.
HTTPKernel should make HTTP execution boring, explicit, and predictable.
It should not become a hidden framework, router, controller system, service container, or process manager.
Architectural Position
A final LiquidRazor HTTP runtime is composed from:
native HTTP runtime adapter
+ liquidrazor/http-contracts
+ liquidrazor/transport-contracts
+ liquidrazor/http-kernel
+ liquidrazor/micro-kernel
+ liquidrazor/diregistry
+ event and process infrastructure
HTTPKernel sits above HTTP contracts and transport contracts, and below application-level HTTP handling.
Application HTTP handler
↑
HTTPKernel
↑
HTTPContracts + TransportContracts
↑
Native HTTP adapter
For isolated execution, HTTPKernel plugs into MicroKernel:
HTTPKernel
-> MicroKernel executable work lifecycle
-> POSIXRuntime-backed worker supervision where available
HTTPKernel does not own the generic lifecycle for workers, scopes, shutdown, or process supervision. Those belong to MicroKernel and POSIXRuntime.
Doctrine
HTTPKernel is the HTTP transport binding for the MicroKernel lifecycle.
It is transport-specific, but lifecycle-subordinate.
It must preserve the core LiquidRazor runtime rule:
The warmed parent owns immutable metadata and parent-safe readonly state.
The forked child owns request execution and mutable runtime state.
The warmed parent must not accidentally instantiate the request execution graph.
The forked child must not mutate global parent state.
HTTPKernel must treat request/response execution as isolated work, not as a method call against a long-lived mutable application object.
Goals
HTTPKernel exists to provide:
- a concrete HTTP transport kernel for LiquidRazor;
- deterministic HTTP request normalization;
- explicit request body normalization through
RequestBodyInterface; - HTTP transport input/output composition;
- HTTP exchange lifecycle progression;
- integration with MicroKernel isolated execution;
- request-scoped DI runtime context creation;
- response finalization through
HttpResponseInterface; - adapter and emitter boundaries for native runtimes;
- HTTP lifecycle event coordination;
- strict separation between parent-warm state and child/request state.
Non-Goals
HTTPKernel does not provide:
- a router;
- route attributes;
- controller discovery;
- controller invocation conventions;
- middleware discovery;
- a PSR-7 implementation;
- a PSR-15 implementation;
- Symfony bridges;
- RoadRunner bridges;
- FrankenPHP bridges;
- SAPI globals capture as a core runtime requirement;
- response emission as a hardcoded runtime behavior;
- service discovery;
- config parsing;
- registry compilation;
- raw process control;
- worker supervision logic;
- a generic web server;
- a replacement for PHP-FPM, RoadRunner, FrankenPHP, Swoole, or another process manager.
Those concerns either belong to other LiquidRazor packages or to separate adapter/bridge packages.
Package Boundary
Expected package identity:
GitHub: https://github.com/LiquidRazor/HTTPKernel
Packagist: liquidrazor/http-kernel
The package should expose reusable HTTP kernel contracts and implementation logic.
It should remain focused on orchestration between HTTP contracts, transport contracts, MicroKernel execution, DI runtime context, and HTTP output finalization.
HTTPKernel should not duplicate responsibilities already owned by upstream packages.
Relationship to Other LiquidRazor Packages
HTTPContracts
Package:
liquidrazor/http-contracts
HTTPContracts owns the HTTP request/response vocabulary.
HTTPKernel consumes:
HttpRequestInterface;HttpResponseInterface;RequestBodyInterface;RequestBodyType;HttpTransportInput;HttpTransportOutput;HttpTransportContext;HttpExchangeInterface;- HTTP lifecycle event objects;
- optional DTO resolver contracts and null defaults.
HTTPKernel must not redefine request, response, request-body, or HTTP exchange contracts locally.
TransportContracts
Package:
liquidrazor/transport-contracts
TransportContracts defines the neutral adapter, input, output, context, pipeline, filter, emitter, status, and exception-mapping vocabulary shared by transport kernels.
HTTPKernel uses those contracts through HTTP-specific implementations supplied by HTTPContracts or by this package where appropriate.
HTTPKernel must not push HTTP semantics back into TransportContracts.
MicroKernel
Package:
liquidrazor/micro-kernel
MicroKernel owns the generic lifecycle for isolated executable work.
HTTPKernel plugs HTTP work into that lifecycle.
HTTPKernel must not reimplement:
- kernel boot lifecycle;
- compile lifecycle;
- container loading lifecycle;
- parent warm lifecycle;
- worker identity;
- worker lifecycle;
- runtime scope lifecycle;
- shutdown lifecycle;
- generic supervision behavior.
POSIXRuntime
Package:
liquidrazor/posix-runtime
POSIXRuntime owns POSIX and PCNTL process primitives used by MicroKernel where forked execution is available.
HTTPKernel must not call raw process-control functions directly.
Raw fork, wait, signal registration, graceful shutdown, and forced termination behavior belong below the HTTPKernel boundary.
DIRegistry
Package:
liquidrazor/diregistry
DIRegistry owns compiled dependency metadata, descriptor resolution, descriptor instantiation, and runtime instance storage.
HTTPKernel may create HTTP request runtime contexts and scope identifiers, but it must not mutate compiled registry metadata or implement its own service resolver.
HTTPKernel must respect the distinction between:
CompiledRegistry = immutable metadata
RuntimeInstanceStore = runtime object state
EventManager
Package:
liquidrazor/event-manager
EventManager owns event contracts, event family validation, registry locking, listener ordering, and synchronous dispatch.
HTTPKernel may coordinate dispatch of HTTP lifecycle events through EventManager infrastructure.
HTTPKernel must not define a separate event system or string-based event naming model.
KernelStateEvents
Package:
liquidrazor/kernel-state-events
KernelStateEvents provides concrete immutable kernel lifecycle events.
HTTPKernel does not define kernel lifecycle events locally.
ProcessEvents
Package:
liquidrazor/process-events
ProcessEvents provides concrete immutable process and worker lifecycle events.
HTTPKernel does not define generic worker events locally.
ConfigLoader, FileLocator, ClassLocator, RegistryLoader
Packages:
liquidrazor/config-loader
liquidrazor/file-locator
liquidrazor/class-locator
liquidrazor/registry-loader
These packages support configuration loading, source discovery, class discovery, and descriptor compilation.
HTTPKernel should consume prepared runtime infrastructure and compiled metadata.
HTTPKernel should not scan files, parse config, discover classes, classify services, or compile registries during request execution.
Execution Model
The intended high-level execution model is:
Parent process:
boot kernel infrastructure
compile immutable metadata
load compiled registry metadata
warm parent-safe readonly state
enter ready state
Per HTTP request:
accept native HTTP input
adapt to HttpRequestInterface
create HttpTransportInput and HttpExchange
pass executable HTTP work into MicroKernel
execute request handling inside isolated child/request scope
produce HttpResponseInterface
finalize HttpTransportOutput
emit native HTTP output
HTTPKernel should make the per-request path explicit:
native input
-> adapter
-> HttpRequestInterface
-> HttpExchange
-> MicroKernel executable work
-> request-scoped handler execution
-> HttpResponseInterface
-> HttpTransportOutput
-> emitter
Warm Parent and Forked Child Boundary
This is the most important runtime boundary in HTTPKernel.
The parent process warms once. Each HTTP request/response cycle executes inside a newly spawned forked child where POSIX execution is available.
Parent-Warm Allowed State
The warmed parent may retain:
- immutable configuration snapshots;
- compiled registry metadata;
- descriptor maps;
- class maps;
- event catalogs;
- locked event registries;
- handler descriptors;
- adapter descriptors;
- emitter descriptors;
- immutable value objects;
- readonly services proven safe for parent retention;
- structural indexes.
Parent-Warm Forbidden State
The warmed parent must not retain:
HttpRequestInterfaceinstances;RequestBodyInterfaceinstances for live requests;HttpResponseInterfaceinstances;HttpExchangeInterfaceinstances for live requests;- request DTOs;
- response DTOs;
- controller or handler instances with mutable state;
- request-scoped services;
- transient request execution graphs;
- uploaded file runtime state;
- open request body streams;
- database connections opened for a request;
- session state;
- authenticated user state;
- mutable logger buffers;
- per-request caches;
- native request resources.
Child/Request-Owned State
The forked child owns:
- HTTP request object;
- normalized request body;
- uploaded file wrappers;
- HTTP exchange state;
- transport context for the request;
- request DTO;
- response DTO;
- handler execution graph;
- mutable runtime services;
- scoped service instances;
- transient service instances;
- response object;
- per-request buffers;
- per-request IO resources;
- child-local failure metadata.
Rule
The parent should retain knowledge about how to execute HTTP work.
The child should execute HTTP work.
Parent: descriptors, metadata, immutable maps.
Child: objects, mutation, request execution, response creation.
HTTP Request Lifecycle
HTTPKernel request handling should follow this logical sequence:
Native HTTP input received
-> adapter normalizes native input
-> HttpRequestInterface created
-> RequestBodyInterface created
-> HttpTransportContext created
-> HttpTransportInput created
-> HttpExchange created
-> HttpRequestReceivedEvent may be emitted
-> HttpRequestPreparedEvent may be emitted
-> request DTO may be resolved
-> HttpRequestDtoResolvedEvent may be emitted
-> executable work enters MicroKernel
The request object models already-normalized HTTP input.
It must not read PHP globals, read php://input, perform routing, validate business input, authorize users, or execute application logic by itself.
HTTP Response Lifecycle
HTTPKernel response handling should follow this logical sequence:
Application handler returns result
-> result is resolved to HttpResponseInterface
-> response DTO may be resolved
-> HttpResponseDtoResolvedEvent may be emitted
-> HttpResponsePreparedEvent may be emitted
-> response is finalized
-> HttpResponseFinalizedEvent may be emitted
-> HttpTransportOutput created
-> emitter receives finalized transport output
The response object describes HTTP output.
It must not emit headers, write output, terminate execution, or depend on a specific native HTTP runtime.
Transport Integration
HTTPKernel uses HTTP-specific transport objects to connect HTTPContracts to TransportContracts.
The HTTP transport name is:
http
HTTP transport input carries an HttpRequestInterface payload.
HTTP transport output carries an HttpResponseInterface payload.
Generic TransportStatus belongs to transport output.
HTTP status code belongs to HttpResponseInterface.
Those two concepts must not be collapsed.
Example distinction:
TransportStatus::Success
HttpResponseInterface::statusCode() === 404
This may represent a successfully executed HTTP request that produced a valid 404 Not Found response.
Runtime Scope Model
Each HTTP request must execute with a request-specific runtime scope.
The scope should be created after the child/request execution boundary begins.
The runtime scope should carry:
- active environment;
- request scope id;
- optional small deterministic runtime parameters;
- HTTP transport context reference where appropriate;
- request correlation/trace identifiers where appropriate.
Scoped services must require a scope id.
Transient services must be created per resolution.
Singleton services retained across fork boundaries are allowed only when they are safe for parent retention.
Resource-bearing, mutable, request-aware, or lazily mutating services must not be instantiated in the warmed parent.
Event Model
HTTPKernel may coordinate HTTP lifecycle events from HTTPContracts.
HTTP lifecycle events should describe HTTP exchange progression only.
Generic kernel lifecycle events belong to KernelStateEvents and are emitted through MicroKernel lifecycle coordination.
Generic worker lifecycle events belong to ProcessEvents and are emitted through MicroKernel/POSIXRuntime coordination.
Event dispatch is synchronous and deterministic through EventManager.
HTTPKernel should not create a second event mechanism.
Adapter and Emitter Model
HTTPKernel should depend on adapter and emitter boundaries instead of hardcoding one native HTTP runtime.
An adapter converts native input into HTTPContracts objects.
An emitter converts finalized HTTP transport output into native runtime output.
Possible adapters and emitters may exist for:
- PHP SAPI;
- PHP-FPM style execution;
- CLI development runner;
- RoadRunner;
- FrankenPHP;
- Swoole;
- custom LiquidRazor runtimes.
Those integrations should be separate adapter or bridge layers unless explicitly scoped into this package later.
Version 0.1.0 should keep adapter and emitter contracts minimal and avoid hardcoding one runtime as the universal model.
Dependency Model
Initial direct dependencies should remain narrow.
Expected direct dependencies:
liquidrazor/http-contracts
liquidrazor/transport-contracts
liquidrazor/micro-kernel
liquidrazor/diregistry
liquidrazor/event-manager
Expected indirect dependencies through MicroKernel:
liquidrazor/kernel-state-events
liquidrazor/process-events
liquidrazor/posix-runtime
Discovery and registry-loading packages should not become direct dependencies unless HTTPKernel explicitly takes responsibility for application bootstrap in a later version.
Avoid direct dependency duplication when an upstream package already provides the required transitive dependency.
Failure Model
HTTPKernel should classify failures rather than letting unrelated exceptions leak randomly through the runtime.
Failure categories include:
- native input adaptation failure;
- request normalization failure;
- request body normalization failure;
- transport context creation failure;
- request DTO resolution failure;
- MicroKernel execution failure;
- handler result validation failure;
- response DTO resolution failure;
- response finalization failure;
- emitter failure;
- child process crash;
- child timeout;
- child cancellation;
- shutdown propagation failure.
HTTP failures should be mappable to HttpResponseInterface where appropriate.
Process and supervision failures should remain visible through MicroKernel/POSIXRuntime result objects and process events.
Public Docs
Focused package docs for the current implementation:
- Execution Flow
- Adapter And Emitter Boundary
- Request Body Normalization
- Runtime Scope
- Failure Mapping
- Fork Safety
Directory Structure
The package follows the standard LiquidRazor library layout:
include/
Contract/
Enum/
Exception/
Value/
lib/
Adapter/
Emitter/
Event/
Execution/
Kernel/
Runtime/
src/
HttpKernel.php
Factory/
tests/
docs/
include/
Contains public HTTPKernel-specific contracts, enums, exceptions, value objects, and definitions.
This layer must not depend on lib/ or src/.
lib/
Contains reusable implementation logic.
This layer may depend on include/ and upstream package contracts, but not on src/.
src/
Contains public runtime integration and package-level wiring.
This layer may depend on include/ and lib/.
Dependency direction remains:
include <- lib <- src
Version 0.1.0 Scope
Version 0.1.0 should prove the full HTTP execution path without adding routing, controllers, or middleware discovery.
Included:
- HTTP kernel orchestration;
- native input adapter boundary;
- HTTP request normalization boundary;
- request body normalization into
RequestBodyInterface; - HTTP transport context/input creation;
- HTTP exchange creation;
- MicroKernel executable work integration;
- request-scoped runtime context creation;
- single configured HTTP handler boundary;
- handler result normalization to
HttpResponseInterface; - HTTP transport output creation;
- response finalization boundary;
- emitter boundary;
- HTTP lifecycle event coordination;
- fork-safety rules for parent and child state.
Excluded:
- routing;
- controller discovery;
- controller invocation conventions;
- route attributes;
- middleware discovery;
- sessions;
- authentication;
- authorization;
- caching;
- CSRF;
- template rendering;
- PSR bridges;
- Symfony bridges;
- RoadRunner bridges;
- FrankenPHP bridges;
- SAPI globals implementation as mandatory core behavior;
- service discovery;
- registry compilation;
- raw process supervision.
The first version should answer one question:
Can LiquidRazor handle one HTTP request as isolated MicroKernel work and return one valid HTTP response without leaking mutable request state into the warmed parent?
Design Constraints
HTTPKernel must follow these constraints:
- PHP 8.3+ minimum unless the framework baseline is raised;
- strict types everywhere;
- no local redefinition of HTTPContracts request/response contracts;
- no local redefinition of TransportContracts core contracts;
- no local redefinition of EventManager event contracts;
- no raw process-control implementation inside HTTPKernel;
- no config parsing inside HTTPKernel;
- no class discovery inside HTTPKernel;
- no registry compilation inside request execution;
- no request objects in warmed parent state;
- no response objects in warmed parent state;
- no mutable handler graph in warmed parent state;
- no resource-bearing services in warmed parent state unless explicitly proven fork-safe;
- request execution must happen inside the child/request lifecycle;
- request-scoped services must require request scope identity;
- runtime failures must be typed or explicitly mapped;
- adapter and emitter behavior must remain runtime-boundary concerns;
- public docs must remain package-facing and standalone.
License
MIT