Middleware Pipeline¶
Xcore uses a compiled middleware pipeline to process every call to a plugin. This pipeline ensures that security, observability, and reliability features are applied consistently and efficiently across the entire ecosystem.
Key Concepts¶
The Execution Flow¶
When xcore.plugins.call() is invoked, the request travels through a series of nested middlewares before finally reaching the plugin's handle() method.
graph TD
A[Supervisor.call] --> M1[IPC Auth]
M1 --> M2[Tracing]
M2 --> M3[Rate Limit]
M3 --> M4[Permissions]
M4 --> M5[Retry]
M5 --> D[Final Dispatch]
D --> P[Plugin.handle]
Compiled for Performance¶
To minimize overhead during high-frequency calls, Xcore compiles the pipeline at boot time into a single chain of nested closures. This avoids the overhead of iterating over lists or repeatedly resolving function names during the request flow.
Standard Middlewares¶
The following middlewares are active by default in the specified order:
1. IPC Auth (IPCAuthMiddleware)¶
Ensures that the caller is authorized to invoke the target plugin.
- Fail-closed: If tenancy.enforce_ipc is true, calls from unauthorized plugins or untrusted sources are blocked.
- Service Bypass: Direct calls from the framework kernel (xcore) are always permitted.
2. Tracing (TracingMiddleware)¶
Automatically starts an OpenTelemetry span for the call.
- Captures plugin_name, action, and caller.
- Records errors and execution duration as span attributes.
3. Rate Limit (RateLimitMiddleware)¶
Enforces the quotas defined in the plugin's plugin.yaml.
- Uses a sliding window algorithm.
- Blocks calls once the calls per period_seconds threshold is exceeded.
4. Permissions (PermissionMiddleware)¶
Evaluates the resource and action against the plugin's PolicySet.
- Replaces the generic execute action with a specific resource string if provided.
- Raises PermissionDenied on failure.
5. Retry (RetryMiddleware)¶
Automatically retries failed calls to Sandboxed plugins if the worker process crashes or the IPC channel times out.
- Configurable via the retry: block in plugin.yaml.
Practical Guide¶
Customizing the Pipeline¶
You can register custom middlewares to add behavior like logging, transformation, or custom authentication.
API Reference¶
Middleware (Abstract Base Class)¶
| Parameter | Type | Description |
|---|---|---|
plugin_name |
str |
Name of the target plugin. |
action |
str |
Action string being invoked. |
payload |
dict |
Input data for the call. |
next_call |
Callable |
The next step in the pipeline (must be awaited). |
handler |
Handler |
The supervisor handler for the target plugin. |
**kwargs |
dict |
Contextual data: caller, tenant_id, resource. |
YAML Configuration¶
The pipeline behavior is influenced by both the global xcore.yaml and individual plugin.yaml files.
| plugin.yaml | |
|---|---|
Common Errors & Pitfalls¶
Forgetting to await next_call
If your middleware doesn't await next_call(...), the pipeline stops immediately and the plugin is never executed.
Middleware Order
The order of registration matters. IPCAuth must always run first to protect the rest of the pipeline from unauthorized calls.
Blocking the Event Loop
Middlewares run in the main thread. Any synchronous, CPU-intensive logic inside a middleware will slow down every plugin call in the system.
Best Practices¶
Keep Middlewares Lean
Middlewares are executed on every single plugin call. Avoid complex logic or database queries inside them; use caching or local state instead.
Use kwargs for Context
If you need to pass data between middlewares, inject it into kwargs. The final _dispatch method and the plugin handle method can access these values.