solrguard includes a first-class Plugin SDK so enterprise and community teams can extend behavior without forking core code.
Core plugin framework files live in schema_lens/plugins/:
base.py: plugin metadata, context, lifecycle base classregistry.py: plugin registration and lookuploader.py: built-in, local directory, and entry-point discoverymanifest.py: plugin run-manifest/artifact modelshooks.py: lifecycle phase nameserrors.py: structured plugin issues/errors
Runtime orchestration is in schema_lens/runtime/plugin_service.py.
Contracts are under schema_lens/plugins/contracts/:
AuthProviderPluginQuerySourcePluginDocSourcePluginReplayExecutorPluginDiffAnalyzerPluginRootCauseRulePluginRecommendationRulePluginGateEvaluatorPluginReportRendererPlugin/ReportWidgetPluginObservabilityExporterPluginRolloutProviderPlugin
Each plugin must define metadata:
nameversiondescriptionplugin_typecompatible_schema_lens_versioncapabilities
Example:
metadata = PluginMetadata(
name="sample_query_source",
version="0.1.0",
plugin_type="query_source",
description="Loads custom query JSON rows",
compatible_schema_lens_version=">=0.1.0",
capabilities=["query_source:file"],
)schema_lens_version remains accepted for backward compatibility.
Plugin lifecycle:
validate_config(config)validate(context)initialize(context)- type-specific hooks (query/doc/gate/report/observability/etc.)
execute(context, payload)(generic finalize stage)cleanup(context)
Errors are isolated and recorded in plugin artifacts and plugins.json. With strict_mode: true, plugin failures block the run.
Implement validate_source(config) and load_queries(config, context):
- Config path from
plugins.config.<plugin_name> - Return list of rows convertible to
QueryCase(for examplequery_text,filters,tenant)
Reference: examples/plugins/sample_query_source/sample_query_source.py
Implement evaluate(policy, artifacts) -> dict:
- Read compare artifacts (for example
compare_data["diffs"]) - Return deterministic pass/fail payload
Reference: examples/plugins/sample_gate/sample_gate.py
Implement:
render_json_section(run_context, artifacts) -> dictrender_html_section(run_context, artifacts) -> str
Reference: examples/plugins/sample_report/sample_report.py
Recommended tests:
- metadata validation
- registry registration/lookup
- loader behavior for built-in/local/entry-point plugins
- strict mode behavior
- compatibility filtering
- exception isolation
- plugin config parsing
- artifact path generation
- plugin integration tests for query source, gate, and report output
Current tests:
tests/test_plugins.pytests/integration/test_plugin_sdk_integration.py
- Declare
compatible_schema_lens_versionconservatively. - If runtime version is outside range, plugin is skipped and logged as compatibility issue.
- Use
plugins.strict_mode: truein CI/production to block incompatible plugins. - Keep plugin contracts deterministic and avoid mutating core artifacts in-place.