Expand description
The generic OpenAPI provider kind: proxies a drop-in provider tool to a
declared base_url + path/method, gated by the manifest’s
capabilities.network.allowed_hosts grant.
§Delegates to soma-openapi
Dispatch goes through soma_openapi::http::execute_operation_for_allowlisted_host
— the same request-building, capped response reading, and JSON
parsing/status handling as soma-openapi’s registry-driven dispatch path
(crates/shared/openapi/src/http.rs). This module keeps only what is
specific to the drop-in-manifest shape: resolving base_url/path/
method out of provider.meta/tool.meta, and the operator-controlled
capabilities.network.allowed_hosts gate.
That entry point (unlike soma_openapi::http::execute_operation, used by
soma-openapi’s own spec-driven dispatch) skips the crate’s DNS-pinned
SSRF guard. This adapter’s trust model is different and is itself part of
the tested, documented contract: an operator explicitly allowlists hosts
via provider.capabilities.network.allowed_hosts, and that allowlist may
legitimately include loopback/private hosts (a local sidecar service, for
example) — see openapi_provider_executes_pinned_local_operation in
apps/soma/tests/openapi_provider.rs, which calls a plain-HTTP
127.0.0.1 server and would be rejected by the DNS-pinned guard. The
allowlist check below (validate_base_url) is this adapter’s own SSRF
defense and runs before any request is dispatched. For that defense to
hold, two things it does NOT rely on soma-openapi for are handled here:
validate_base_url fails closed (denies dispatch) when a provider’s
capabilities.network grant is absent or disabled, rather than treating
that as “no restriction needed”; and dispatch_client disables HTTP
redirects, so an allowlisted host can’t hand a request off to a
non-allowlisted address via a 3xx response.
A small amount of behavior differs from the pre-delegation implementation, documented here rather than hidden:
{name}placeholders in a declared operationpathare now honored as path parameters (previously inert literal text); this is additive.- An operation path that resolves outside the declared
base_url’s own path prefix (e.g. via..segments) is now rejected; previously unchecked. call.paramsmust now be a JSON object for every method, not only GET/DELETE; previously POST/PUT/PATCH accepted any JSON value as the request body.- A non-2xx upstream response no longer includes the HTTP status code in
the error message (the
openapi_upstream_errorerrorcodeis unchanged).