diff --git a/docs/build-plugins/register-behavior.mdx b/docs/build-plugins/register-behavior.mdx index 1e37467a..d995ca77 100644 --- a/docs/build-plugins/register-behavior.mdx +++ b/docs/build-plugins/register-behavior.mdx @@ -25,82 +25,6 @@ That gives the plugin system three important guarantees: Use the context only after validation succeeds. Validation should inspect config and return diagnostics; registration should create runtime objects and attach them to the context. -## Activation APIs - -Use the plugin APIs in this order: - -1. Register the plugin kind. -2. Build a `PluginConfig`. -3. Validate the config. -4. Initialize the config. -5. Inspect the activation report. -6. Clear active config during teardown when needed. - - - -```python -import nemo_relay - -config = nemo_relay.plugin.PluginConfig() -config.components = [ - nemo_relay.plugin.ComponentSpec( - kind="header-plugin", - config={"header_name": "x-tenant", "value": "tenant-a"}, - ) -] - -report = nemo_relay.plugin.validate(config) -active_report = await nemo_relay.plugin.initialize(config) -kinds = nemo_relay.plugin.list_kinds() -nemo_relay.plugin.clear() -``` - - - - -```ts -import * as plugin from 'nemo-relay-node/plugin'; - -const config = plugin.defaultConfig(); -config.components = [ - plugin.ComponentSpec( - 'header-plugin', - { header_name: 'x-tenant', value: 'tenant-a' }, - { enabled: true }, - ), -]; - -const report = plugin.validate(config); -const activeReport = await plugin.initialize(config); -const kinds = plugin.listKinds(); -plugin.clear(); -``` - - - - -```rust -use nemo_relay::plugin::{ - clear_plugin_configuration, initialize_plugins, list_plugin_kinds, validate_plugin_config, - PluginComponentSpec, PluginConfig, -}; - -let mut config = PluginConfig::default(); -let mut component = PluginComponentSpec::new("header-plugin"); -component.config.insert("header_name".into(), "x-tenant".into()); -component.config.insert("value".into(), "tenant-a".into()); -config.components.push(component); - -let report = validate_plugin_config(&config); -let active_report = initialize_plugins(config).await?; -let kinds = list_plugin_kinds(); -clear_plugin_configuration()?; -``` - - - - - ## Header Plugin Example The same model applies in every binding: validate component-local config, then install middleware through the component-scoped registration context. @@ -257,6 +181,83 @@ register_plugin(Arc::new(HeaderPlugin))?; +## Activation APIs + +With the plugin kind registered (see the Header Plugin Example above), use the plugin APIs in this order: + +1. Build a `PluginConfig`. +2. Validate the config. +3. Initialize the config. +4. Inspect the activation report. +5. Clear active config during teardown when needed. + +Register the plugin kind before you initialize. An unregistered kind is reported by `validate()` only as a warning under the default `unknown_component="warn"` policy, so an error-only check still passes, but `initialize()` raises for a kind that was never registered. + + + +```python +import nemo_relay + +config = nemo_relay.plugin.PluginConfig() +config.components = [ + nemo_relay.plugin.ComponentSpec( + kind="header-plugin", + config={"header_name": "x-tenant", "value": "tenant-a"}, + ) +] + +report = nemo_relay.plugin.validate(config) +active_report = await nemo_relay.plugin.initialize(config) +kinds = nemo_relay.plugin.list_kinds() +nemo_relay.plugin.clear() +``` + + + + +```ts +import * as plugin from 'nemo-relay-node/plugin'; + +const config = plugin.defaultConfig(); +config.components = [ + plugin.ComponentSpec( + 'header-plugin', + { header_name: 'x-tenant', value: 'tenant-a' }, + { enabled: true }, + ), +]; + +const report = plugin.validate(config); +const activeReport = await plugin.initialize(config); +const kinds = plugin.listKinds(); +plugin.clear(); +``` + + + + +```rust +use nemo_relay::plugin::{ + clear_plugin_configuration, initialize_plugins, list_plugin_kinds, validate_plugin_config, + PluginComponentSpec, PluginConfig, +}; + +let mut config = PluginConfig::default(); +let mut component = PluginComponentSpec::new("header-plugin"); +component.config.insert("header_name".into(), "x-tenant".into()); +component.config.insert("value".into(), "tenant-a".into()); +config.components.push(component); + +let report = validate_plugin_config(&config); +let active_report = initialize_plugins(config).await?; +let kinds = list_plugin_kinds(); +clear_plugin_configuration()?; +``` + + + + + ## Registration Checklist Before publishing or sharing a plugin: diff --git a/docs/build-plugins/validate-configuration.mdx b/docs/build-plugins/validate-configuration.mdx index e59f8c30..f420768c 100644 --- a/docs/build-plugins/validate-configuration.mdx +++ b/docs/build-plugins/validate-configuration.mdx @@ -126,6 +126,14 @@ Prefer stable diagnostic codes over prose-only messages. The message can improve Use the validation API before initialization and fail deployment if the report contains errors. + +This error check does not catch an unknown or unregistered component kind. Under +the default `unknown_component="warn"` policy that case is reported as a warning, +not an error, so the check below passes while `initialize()` still raises for a +kind that is not registered. Register every kind before initialization, or set +`unknown_component="error"` to make validation fail on unknown kinds. + + ```python