# folk-api

Plugin contract crate for the Folk PHP application server. All Folk plugins depend only on this crate.

**Version:** 0.2.0

## Key traits

- **`Executor`** -- dispatches work to PHP workers. Two methods:
  - `execute_method(payload: Bytes) -> Result<Bytes>` -- raw bytes dispatch
  - `execute_value(value: serde_json::Value) -> Result<serde_json::Value>` -- zero-copy dispatch via `serde_json::Value`, no serialization round-trip. **Preferred path.**
- **`Plugin`** -- lifecycle: `name()`, `boot(ctx)`, `shutdown()`. Optional: `rpc_methods()`.
- **`ServerPlugin`** -- convenience trait for long-lived tasks. Wrap with `ServerPluginWrapper` to get a `Plugin`.
- **`PluginFactory`** -- `create(config: Value) -> Result<Box<dyn Plugin>>`. Called once per plugin crate by the builder.
- **`RpcRegistrar`** -- register admin RPC methods via `register_raw(name, handler)`.

## PluginContext

Every plugin receives a `PluginContext` at boot:

| Field | Type | Description |
|-------|------|-------------|
| `executor` | `Arc<dyn Executor>` | Dispatch work to PHP workers |
| `shutdown` | `watch::Receiver<bool>` | Fires on server shutdown |
| `rpc_registrar` | `Option<Arc<dyn RpcRegistrar>>` | Register admin RPC methods |
| `health_registry` | `Option<Arc<dyn HealthRegistry>>` | Register health checks |
| `metrics_registry` | `Option<Arc<dyn MetricsRegistry>>` | Register Prometheus metrics |

Optional registries are `None` when the corresponding plugin is not loaded.

## Plugin lifecycle

1. **Factory** -- `folk_plugin_factory()` returns a `PluginFactory`.
2. **Boot** -- `plugin.boot(ctx)` in registration order. `Err` is fatal.
3. **Run** -- `ServerPlugin::run()` executes as a long-lived task. Watch `ctx.shutdown`.
4. **Shutdown** -- `plugin.shutdown()` in reverse order.

## Installation

```toml
folk-api = "0.2"
```

## Requirements

- Rust 1.88+

## License

MIT
