The AssemblyLoadContext isolation claim being scoped honestly is what makes this trustworthy, it explicitly says isolation ≠ security boundary, since plugin code still runs with the host's OS identity and memory access. A lot of plugin-architecture writeups blur that line and let readers assume more safety than the CLR loader actually provides.
Hot replacement being flagged as "a different architecture, not a small addition" is the right call. Marking a load context collectible doesn't make anything swappable while the root service provider, event subscriptions, timers, and cached reflection objects all still hold references, cooperative unloading only happens once every one of those is gone, which is a much bigger design commitment than it sounds.
The path-traversal warning on the plugin manifest loader is a small detail but the kind that's easy to skip in a "here's how plugins work" tutorial, accepting an arbitrary entry path from config or a request would turn the loader itself into an RCE vector, and validating that the resolved path stays inside the plugin root is a one-line check most examples wouldn't bother showing.
The AssemblyLoadContext isolation claim being scoped honestly is what makes this trustworthy, it explicitly says isolation ≠ security boundary, since plugin code still runs with the host's OS identity and memory access. A lot of plugin-architecture writeups blur that line and let readers assume more safety than the CLR loader actually provides.
Hot replacement being flagged as "a different architecture, not a small addition" is the right call. Marking a load context collectible doesn't make anything swappable while the root service provider, event subscriptions, timers, and cached reflection objects all still hold references, cooperative unloading only happens once every one of those is gone, which is a much bigger design commitment than it sounds.
The path-traversal warning on the plugin manifest loader is a small detail but the kind that's easy to skip in a "here's how plugins work" tutorial, accepting an arbitrary entry path from config or a request would turn the loader itself into an RCE vector, and validating that the resolved path stays inside the plugin root is a one-line check most examples wouldn't bother showing.