Turns a plugin identifier into its directory name under the plugins root. Shared between backend
and frontend on purpose: two independent encodings would disagree on some identifier and produce
two directories for one plugin, which is what adoption exists to prevent.
Error when the identifier does not encode to a usable single path segment. The name
comes from registry JSON, so this is what stops a .. escaping the plugins root.
Turns a plugin identifier into its directory name under the plugins root. Shared between backend and frontend on purpose: two independent encodings would disagree on some identifier and produce two directories for one plugin, which is what adoption exists to prevent.