Decouple plugin manifest path resolution (#29620)

## Why

Plugin manifests use the same schema whether the package lives on the
host or in an executor. Only the path representation differs: host
callers need native `Path` inputs and `AbsolutePathBuf` outputs, while
executor callers need `PathUri` throughout.

Maintaining separate parsing or resolver implementations would duplicate
the manifest rules and allow them to drift. This PR instead makes
URI-native resolution the single parsing path and keeps host conversion
at the boundary.

## What changed

- Make `parse_plugin_manifest_uri` the shared manifest parser and
resolve every path-bearing field as `PathUri`.
- Keep the existing host entrypoint as a thin adapter: convert its
native root and manifest path to `PathUri`, run the shared parser, then
map resources back to `AbsolutePathBuf`.
- Expose `PluginManifest::try_map_resources` so callers can convert the
generic resource type without duplicating manifest construction.
- Resolve relative manifest paths using the root URI's convention:
backslashes are separators for Windows roots and ordinary filename
characters for POSIX roots.
- Apply lexical containment after URI resolution, rejecting absolute
paths and parent traversal outside the plugin root.
- Make encoded backslashes fail containment only for Windows URIs;
encoded `/` remains unsafe for every convention.
- Use a host-native synthetic root for marketplace fallback manifests so
the host adapter also works on Windows.

```text
host Path --------> PathUri --\
                              +--> one manifest parser --> PluginManifest<PathUri>
executor PathUri -------------/

host result: PluginManifest<PathUri> --> PluginManifest<AbsolutePathBuf>
```

Existing host manifest behavior is preserved; #28918 is the first
executor consumer.

## Verification

- `just test -p codex-utils-path-uri`
- `just test -p codex-plugin`
- `just test -p codex-core-plugins`

## Stack

1. #29614 — add lexical `PathUri` containment.
2. **This PR** — share URI-native manifest path resolution.
3. #28918 — keep selected plugin roots and resources URI-native.
4. #29626 — load executor skills without host path conversion.
5. #29628 — resolve executor MCP working directories without host path
conversion.
This commit is contained in:
jif
2026-06-23 20:33:59 +00:00
committed by GitHub
parent 50eee505a3
commit f6500886b7
5 changed files with 149 additions and 62 deletions
+2 -1
View File
@@ -90,7 +90,8 @@ impl<Resource> PluginManifest<Resource> {
.unwrap_or(&self.name)
}
pub(crate) fn try_map_resources<Mapped, Error>(
/// Maps every path-bearing resource in the manifest.
pub fn try_map_resources<Mapped, Error>(
self,
mut map: impl FnMut(Resource) -> Result<Mapped, Error>,
) -> Result<PluginManifest<Mapped>, Error> {