Add ServerAgentFactory SPI for extension-contributed agents#2130
Add ServerAgentFactory SPI for extension-contributed agents#2130krital wants to merge 3 commits into
Conversation
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
….agents.allowed allowlist
Addressing the security review concern (allowlist added — commit 975ac08)Thanks for flagging the plugin-loading risk. I've pushed a defense-in-depth change and want to lay out the reasoning. The change: An un-listed factory is skipped with a log line rather than started. No jar can auto-run an agent just by being present. On the underlying trust boundary: it's worth noting the SPI does not create a new code-execution path. Anyone who can write a jar into Note: the extension it was built for (tailnet onboarding) can now also run fully out-of-process (a standalone launcher against a stock server), so this SPI is a convenience for in-process integration, not a hard dependency — no rush if you'd like more time on it. Happy to adjust: e.g. gate the allowlist itself behind a licensed feature, require signed jars, or default to a specific known-good set instead of empty. Whatever you're most comfortable with. |
Summary
Adds a generic extension point so third-party jars can contribute a lifecycle
Agentto the server viajava.util.ServiceLoader, without any core edits per extension.io.mapsmessaging.ServerAgentFactoryinterface:Agent create(),int startOrder(),int stopOrder().SubSystemManager.createAgentStartStopList()now callsloadExtensionAgents(), which discovers allServerAgentFactoryproviders and registers each returnedAgentwith its start/stop ordering (added after the built-in agents, so ordering composes correctly).loadProtocolImplementations()pattern:iterator.next()is inside thetry, so aServiceConfigurationErrorfrom a malformedMETA-INF/servicesentry or a factory that fails to instantiate is caught per-provider and cannot crash daemon startup.getName()collides with an already-registered agent is skipped (can't silently shadow a core manager inagentMap).MESSAGE_DAEMON_EXTENSION_AGENT_FAILED(WARN), distinct from the fatal core-agent path (which reads "system exitting").Motivation: the first MAPS extension (tailnet onboarding) needs to run a long-lived subsystem inside the daemon. The
EndPointServerFactoryroute can't bind a custom-scheme endpoint (EndPointConfigFactoryreturns null for unknown schemes, unlike the protocol side'sExtensionConfigfallback), so a general Agent SPI is the clean seam.Changes
src/main/java/io/mapsmessaging/ServerAgentFactory.java(new)src/main/java/io/mapsmessaging/SubSystemManager.java(+loadExtensionAgents()+ call)src/main/java/io/mapsmessaging/logging/ServerLogMessages.java(+MESSAGE_DAEMON_EXTENSION_AGENT_FAILED)Test Plan
mvn -DskipTests installbuilds; artifact containsio.mapsmessaging.ServerAgentFactory.ServerAgentFactoryproviders are present (additive, no built-in agents changed).maps-tailnet-onboardingextension: dropping its jar in/opt/maps/lib/loadsTailnetAgent(Service Manager Tailnet Onboarding loaded→Started Tailnet Onboarding), noNetworkManager.yamlentry needed.create()) logs a WARN and does not crash startup.🤖 Generated with Claude Code