Summary
A gateway plugin can serve HTTP routes that appear nowhere in the OpenAPI document, and nothing reports it.
PluginManager mounts whatever GatewayPlugin::get_routes() returns. Route descriptions come from a separate, optional export: the manager looks up describe_plugin_routes with dlsym, and when the symbol is missing it skips the plugin without a message (plugin_manager.cpp, "Plugin doesn't export route descriptions - skip silently").
So a plugin that returns routes but does not export describe_plugin_routes gets its routes served and undocumented. RouteRegistry::validate_completeness() cannot catch this, because it walks only the routes registered in the registry and a plugin route never enters it.
The graph provider does export the symbol, so the shipped set is documented today. The gap is that nothing keeps it that way, and nothing tells an author of a new plugin that they missed it.
Proposed solution (optional)
Report the case instead of skipping it. When a plugin returns a non-empty route list but exports no describe_plugin_routes, log a warning at startup naming the plugin and how many routes are undocumented. A plugin with no routes needs no description and should stay silent.
Making it a hard error was considered and rejected for now: it would break any out-of-tree plugin that has routes and no description export, including ones we do not control. A warning first, and a decision about promoting it to an error once the in-tree plugins and the documented plugin contract agree.
Additional context (optional)
Related: describe_plugin_routes output is written by hand and is not tied to PluginRoute::handler. A plugin can therefore describe one path and mount another, or describe a request field its handler rejects. Worth considering together with the above when the plugin contract is next revised.
Summary
A gateway plugin can serve HTTP routes that appear nowhere in the OpenAPI document, and nothing reports it.
PluginManagermounts whateverGatewayPlugin::get_routes()returns. Route descriptions come from a separate, optional export: the manager looks updescribe_plugin_routeswithdlsym, and when the symbol is missing it skips the plugin without a message (plugin_manager.cpp, "Plugin doesn't export route descriptions - skip silently").So a plugin that returns routes but does not export
describe_plugin_routesgets its routes served and undocumented.RouteRegistry::validate_completeness()cannot catch this, because it walks only the routes registered in the registry and a plugin route never enters it.The graph provider does export the symbol, so the shipped set is documented today. The gap is that nothing keeps it that way, and nothing tells an author of a new plugin that they missed it.
Proposed solution (optional)
Report the case instead of skipping it. When a plugin returns a non-empty route list but exports no
describe_plugin_routes, log a warning at startup naming the plugin and how many routes are undocumented. A plugin with no routes needs no description and should stay silent.Making it a hard error was considered and rejected for now: it would break any out-of-tree plugin that has routes and no description export, including ones we do not control. A warning first, and a decision about promoting it to an error once the in-tree plugins and the documented plugin contract agree.
Additional context (optional)
Related:
describe_plugin_routesoutput is written by hand and is not tied toPluginRoute::handler. A plugin can therefore describe one path and mount another, or describe a request field its handler rejects. Worth considering together with the above when the plugin contract is next revised.