Skip to content

Bamboo v0.3 Middleware & Module Preparation

This document captures the design notes for the middleware pipeline and module system that will land in the v0.3 release. It is intended to guide feature work before the implementation solidifies so teams can agree on naming, execution order, and container responsibilities.

Middleware pipeline architecture

Execution order

  1. Global stack – middleware defined in etc/middleware.php under the global key runs for every HTTP request. These entries are resolved out of the container, allowing dependencies to be injected through constructor arguments.
  2. Grouped layers – route definitions will reference named groups. Each group is resolved from the configuration file and merged onto the global stack in the order the groups are attached to the route. This keeps common policies (e.g., authentication, throttling) reusable without repeating class names per route.
  3. Route-specific middleware – ad-hoc middleware declared directly on a route are appended last so teams can override behaviors on a single endpoint without mutating global state.
  4. Termination hooks – middleware implementing a terminate() method will be collected during request execution and invoked after the response is sent so they can perform cleanup or async dispatching.

Grouping strategy

  • etc/middleware.php will return a keyed array of middleware identifiers. The top-level keys are global, groups, and aliases.
  • Global middleware lists the always-on stack.
  • Groups are keyed by group name and contain ordered middleware class strings or alias references. Groups may be nested by referencing other group names, enabling composition (e.g., web can include session and csrf groups).
  • Aliases map short handles to class strings so routing declarations stay readable and avoid hard-coding fully-qualified class names.

Container integration

  • The HTTP kernel will pull middleware definitions from the resolved configuration (Bamboo\Core\Config).
  • Each middleware entry is resolved through the service container to honour constructor dependencies.
  • The kernel will cache the expanded stack for each route to avoid rebuilding the same array on every request. Cache invalidation happens when the route cache is cleared or when configuration files change.

Module contract

Modules expose extension points for the framework. The proposed Bamboo\Module\ModuleInterface formalizes how a module registers its services and middleware contributions.

namespace Bamboo\Module;

use Bamboo\Core\Application;

interface ModuleInterface
{
    /**
     * Register bindings or configuration into the container.
     */
    public function register(Application $app): void;

    /**
     * Perform post-registration boot logic once all modules are loaded.
     */
    public function boot(Application $app): void;

    /**
     * Optionally contribute middleware aliases or stacks.
     *
     * @return array<string, array<int, string>|string>
     */
    public function middleware(): array;
}

Additional optional contracts (such as provides() for deferred loading) can be introduced in later iterations, but the above set keeps the initial API small and focused on container registration.

Module registration flow

  1. Modules are declared in etc/modules.php as an ordered list of class names implementing ModuleInterface.
  2. During bootstrap the application resolves the array, iterates through each module, and calls register() so services, configuration, and bindings are available before the rest of the framework boots.
  3. After all modules have registered, the bootstrapper calls boot() on each module in registration order. This ensures modules can safely interact with services from other modules.
  4. Middleware contributions returned by middleware() are merged into the configuration structure loaded from etc/middleware.php, allowing modules to publish additional aliases or group entries.
  5. Future tooling (e.g., bin/bamboo modules.list) can introspect the configuration and report which modules are active and what middleware they expose.

Configuration entry points

  • etc/middleware.php – placeholder returning an empty array today. Teams will populate the global, groups, and aliases keys described above as middleware lands in the codebase.
  • etc/modules.php – placeholder returning an empty array. Populate it with module class names in the order they should be registered with the application container.

Link this document in the README so contributors know where the roadmap lives and where to wire upcoming configuration.