Audited: the providers feature surface of mnfst/manifest at PR #2705 (commit 126bd7ff8), against the docs at 278ed8b. Scoped nightly rotation run (topic: providers). Window: full provider surface, ~60 days of merged PRs (through #2705) plus the current provider registry and routing code.
Pages in scope:
Findings
1 · [MISSING-CASE] Local models are blocked entirely on Manifest Cloud, but the Local models page presents them as available everywhere
Page: https://manifest.build/docs/providers/local-models (whole page, especially "Connect to Manifest")
What actually happens:
- On self-hosted Manifest, the Ollama, LM Studio, and llama.cpp tiles appear on the Routing page and work as the page describes.
- On Manifest Cloud, those tiles do not appear and cannot be connected.
- A Cloud user who reaches a local provider by any path (connect, model discovery, or a routed request) is rejected: "Built-in local providers are only available in self-hosted Manifest. On Manifest Cloud, expose the runtime through a public URL or tunnel and connect it as a custom provider." A routed request fails with error M303.
- The only way to reach a local model from Cloud is a custom provider pointed at a public URL or tunnel.
Options:
- Add a Cloud callout near the top of the page: the built-in local tiles are self-hosted only, and on Cloud you expose the runtime on a public URL/tunnel and add it as a custom provider. Recommended.
- Wrap the connect flow in the cloud/self-hosted toggle, showing the custom-provider route on the Cloud side.
- Note the restriction in one sentence under "Connect to Manifest" only.
Suggested wording (option 1), a callout to place after the intro paragraph:
<Note>
The built-in Ollama, LM Studio, and llama.cpp tiles are self-hosted only. On [Manifest Cloud](https://app.manifest.build) they don't appear and can't be connected. To reach a local model from Cloud, expose the runtime on a public URL or tunnel and add it as a [custom provider](/providers/custom-providers).
</Note>
Evidence (for the agent)
providers/local-models.mdx:9 — "Manifest detects the running server, fetches the model list, and routes requests to http://localhost:<port> like any other provider."
providers/local-models.mdx:46-56 — the "Connect to Manifest" flow ("click the runtime tile (Ollama, LM Studio, or llama.cpp)") with no deployment caveat.
- Code:
provider-availability.ts:15-17 isProviderAvailableForDeployment = isSelfHosted() || !isLocalOnlyProvider(p); message provider-availability.ts:4-5; blocked at connect provider.controller.ts:115-120, discovery model.controller.ts:110-112 + model-discovery.service.ts:399-406, proxy provider-client.ts:260-262 (M303, error-codes.ts:75-79). Tiles hidden on Cloud by filterProvidersForDeployment. Gate is isSelfHosted() (detect-self-hosted.ts:16-25). PR #2535.
- Impact: a Cloud user follows the page, finds no runtime tiles, and never learns the documented workaround (custom provider on a public URL).
2 · [WRONG] The GLM Coding Plan tab names only the China endpoint; the global default routes to api.z.ai
Page: https://manifest.build/docs/providers/subscription-based-providers ("How auth works per provider", GLM Coding Plan tab)
What actually happens:
- You paste a GLM (Z.ai) subscription token and pick a region: global or China.
- On the global default, requests route to
api.z.ai/api/coding/paas/v4.
- Only the China region routes to
open.bigmodel.cn/api/coding/paas/v4.
- The doc names only the China host, so a user allowlisting egress destinations allowlists the wrong host and mis-reads where their traffic goes.
Fix: show both endpoints like the MiniMax tab on the same page already does.
Suggested wording (replaces the GLM Coding Plan tab body):
<Tab title="GLM Coding Plan">
Paste the subscription token issued by Z.ai. Requests route to
`api.z.ai/api/coding/paas/v4` (global) or
`open.bigmodel.cn/api/coding/paas/v4` (China).
</Tab>
Evidence (for the agent)
providers/subscription-based-providers.mdx:79-82 — "Paste the subscription token issued by Z.ai. Requests route to open.bigmodel.cn/api/coding/paas/v4/chat/completions."
- Code:
zai-region.ts:2-3 — global https://api.z.ai/api/coding/paas/v4, cn https://open.bigmodel.cn/api/coding/paas/v4; region accepted for zai subscription at provider.controller.ts:137-154.
- The same page's MiniMax tab (
:74-77) already shows both global and China hosts; the GLM tab shows only China.
3 · [WRONG] The custom-provider Security note invents an "on the same network" condition; the real gate is deployment mode
Page: https://manifest.build/docs/providers/custom-providers ("Security")
What actually happens:
- On self-hosted Manifest, private IPs (
10.x, 192.168.x, 127.x, link-local, and similar) and plain http:// URLs are accepted, regardless of subnet. There is no "same network" check.
- On Manifest Cloud, private and internal targets are rejected: the URL must be a public
https:// endpoint.
- Cloud-metadata addresses (
169.254.169.254 and similar) are blocked in both modes, even self-hosted.
- A self-hosted user pointing at a private endpoint on another subnet believes it is blocked (it is not); a Cloud user is never told a private or
http:// endpoint cannot work at all.
Fix: state the rule by deployment mode and keep the "revalidated on every request" sentence.
Suggested wording (replaces the Security paragraph at line 54; the <Warning> below it stays):
User-supplied URLs are revalidated on every request to defend against SSRF. On Manifest Cloud, a custom provider must use a public `https://` URL: Manifest rejects private and internal targets (`10.x`, `192.168.x`, `127.x`, link-local, and similar). Self-hosted deployments accept private addresses and plain `http://`, so they can reach a server inside your own network. Cloud-metadata addresses like `169.254.169.254` are blocked in both modes.
Evidence (for the agent)
providers/custom-providers.mdx:54 — "Manifest blocks resolution to private IP ranges (10.x, 192.168.x, 127.x, link-local, etc.) unless the request originates from a self-hosted instance on the same network."
- Code:
custom-provider.service.ts:214,297,429 validatePublicUrl(url,{allowPrivate: isSelfHosted()}); blocked ranges url-validation.ts:4-17; cloud-metadata always blocked url-validation.ts:103-127,166-169. No network-topology / "same network" concept exists in the code.
- The page's own example
providers/custom-providers.mdx:30 uses https://my-vllm.internal:8000/v1, an internal host that a Cloud instance would reject, which is exactly the case the note should split by mode.
4 · [WRONG, low severity] Bedrock and NVIDIA NIM are listed as having "no fixed prefix", but their key fields show ABSK and nvapi-
Page: https://manifest.build/docs/providers/api-key-providers ("Key prefixes")
What actually happens:
- The key-prefix table is a paste-check aid ("useful for catching paste mistakes"), not an enforced rule.
- The doc lists Cerebras, NVIDIA NIM, AWS Bedrock, Kilo, and OpenCode Zen as having no fixed prefix.
- AWS Bedrock bearer tokens carry the
ABSK prefix and NVIDIA NIM keys carry nvapi-; both show as the connect-form placeholder.
- Cerebras, Kilo, and OpenCode Zen genuinely have no prefix, so the line is right for three of the five and wrong for two.
Options:
- Add
AWS Bedrock → ABSK and NVIDIA NIM → nvapi- to the prefix table and shorten the no-prefix sentence to Cerebras, Kilo, OpenCode Zen. Recommended.
- Leave as-is: prefixes are unenforced branding, so no request is blocked by this.
Suggested wording (option 1), two new table rows plus the revised sentence:
| AWS Bedrock | `ABSK` | `ABSK...` |
| NVIDIA NIM | `nvapi-` | `nvapi-...` |
Providers not listed here (Cerebras, Kilo, OpenCode Zen) issue keys with no fixed prefix.
Evidence (for the agent)
providers/api-key-providers.mdx:90 — "Providers not listed here (Cerebras, NVIDIA NIM, AWS Bedrock, Kilo, OpenCode Zen) issue keys with no fixed prefix."
- Code: bedrock key prefix
ABSK (bedrock-region.ts AWS_BEARER_TOKEN_PREFIX, legacy bedrock-api-key-); nvidia key prefix placeholder nvapi-. Prefixes are UI placeholders/branding, not enforced server-side.
- Impact: a Bedrock or NVIDIA user checking their key against the section meant to reassure them sees a contradiction between the doc and the
ABSK/nvapi- placeholder in the form.
5 · [IMAGE] The "Add a provider" flow describes the Routing tile grid in words only
Page: https://manifest.build/docs/providers/api-key-providers ("Add a provider", the "Open the Routing page" step)
A screenshot of the Routing page tile grid belongs under the "Add a provider" steps.
Evidence (for the agent)
providers/api-key-providers.mdx:53-65 — the three-step flow ("navigate to Routing... You'll see a tile for every supported provider") describes the tile grid with no image.
- The Routing tile grid is the shared entry point reused by all four in-scope provider pages, and a first-time user has no visual anchor for where the tiles are.
6 · [IMAGE] The API Key vs Subscription two-tab panel is described but not shown
Page: https://manifest.build/docs/providers/subscription-based-providers ("Connect a subscription", the "Pick the Subscription tab" step)
A screenshot of a dual-auth provider panel showing the two tabs (API Key and Subscription) belongs under the "Pick the Subscription tab" step, so users see where the tab switch is before following the prose.
Evidence (for the agent)
providers/subscription-based-providers.mdx:41-45 — "Providers that take either credential show two tabs (API Key and Subscription); pick Subscription."
- The dual-auth choice is central to this page (ten dual-auth providers); the tab UI is prose-only.
Reply with the finding number and the chosen option
(e.g. "3 → option 2", or "3: other idea, let's discuss").
PRs are then made manually with the agent, never by the harness.
Rejected findings: reply "N → reject" and they will never be re-raised.
Audited: the providers feature surface of mnfst/manifest at PR #2705 (commit 126bd7ff8), against the docs at 278ed8b. Scoped nightly rotation run (topic: providers). Window: full provider surface, ~60 days of merged PRs (through #2705) plus the current provider registry and routing code.
Pages in scope:
Findings
1 · [MISSING-CASE] Local models are blocked entirely on Manifest Cloud, but the Local models page presents them as available everywhere
Page: https://manifest.build/docs/providers/local-models (whole page, especially "Connect to Manifest")
What actually happens:
Options:
Suggested wording (option 1), a callout to place after the intro paragraph:
Evidence (for the agent)
providers/local-models.mdx:9— "Manifest detects the running server, fetches the model list, and routes requests tohttp://localhost:<port>like any other provider."providers/local-models.mdx:46-56— the "Connect to Manifest" flow ("click the runtime tile (Ollama, LM Studio, or llama.cpp)") with no deployment caveat.provider-availability.ts:15-17isProviderAvailableForDeployment = isSelfHosted() || !isLocalOnlyProvider(p); messageprovider-availability.ts:4-5; blocked at connectprovider.controller.ts:115-120, discoverymodel.controller.ts:110-112+model-discovery.service.ts:399-406, proxyprovider-client.ts:260-262(M303,error-codes.ts:75-79). Tiles hidden on Cloud byfilterProvidersForDeployment. Gate isisSelfHosted()(detect-self-hosted.ts:16-25). PR #2535.2 · [WRONG] The GLM Coding Plan tab names only the China endpoint; the global default routes to api.z.ai
Page: https://manifest.build/docs/providers/subscription-based-providers ("How auth works per provider", GLM Coding Plan tab)
What actually happens:
api.z.ai/api/coding/paas/v4.open.bigmodel.cn/api/coding/paas/v4.Fix: show both endpoints like the MiniMax tab on the same page already does.
Suggested wording (replaces the GLM Coding Plan tab body):
Evidence (for the agent)
providers/subscription-based-providers.mdx:79-82— "Paste the subscription token issued by Z.ai. Requests route toopen.bigmodel.cn/api/coding/paas/v4/chat/completions."zai-region.ts:2-3— globalhttps://api.z.ai/api/coding/paas/v4, cnhttps://open.bigmodel.cn/api/coding/paas/v4; region accepted for zai subscription atprovider.controller.ts:137-154.:74-77) already shows both global and China hosts; the GLM tab shows only China.3 · [WRONG] The custom-provider Security note invents an "on the same network" condition; the real gate is deployment mode
Page: https://manifest.build/docs/providers/custom-providers ("Security")
What actually happens:
10.x,192.168.x,127.x, link-local, and similar) and plainhttp://URLs are accepted, regardless of subnet. There is no "same network" check.https://endpoint.169.254.169.254and similar) are blocked in both modes, even self-hosted.http://endpoint cannot work at all.Fix: state the rule by deployment mode and keep the "revalidated on every request" sentence.
Suggested wording (replaces the Security paragraph at line 54; the
<Warning>below it stays):Evidence (for the agent)
providers/custom-providers.mdx:54— "Manifest blocks resolution to private IP ranges (10.x,192.168.x,127.x, link-local, etc.) unless the request originates from a self-hosted instance on the same network."custom-provider.service.ts:214,297,429validatePublicUrl(url,{allowPrivate: isSelfHosted()}); blocked rangesurl-validation.ts:4-17; cloud-metadata always blockedurl-validation.ts:103-127,166-169. No network-topology / "same network" concept exists in the code.providers/custom-providers.mdx:30useshttps://my-vllm.internal:8000/v1, an internal host that a Cloud instance would reject, which is exactly the case the note should split by mode.4 · [WRONG, low severity] Bedrock and NVIDIA NIM are listed as having "no fixed prefix", but their key fields show
ABSKandnvapi-Page: https://manifest.build/docs/providers/api-key-providers ("Key prefixes")
What actually happens:
ABSKprefix and NVIDIA NIM keys carrynvapi-; both show as the connect-form placeholder.Options:
AWS Bedrock → ABSKandNVIDIA NIM → nvapi-to the prefix table and shorten the no-prefix sentence to Cerebras, Kilo, OpenCode Zen. Recommended.Suggested wording (option 1), two new table rows plus the revised sentence:
Evidence (for the agent)
providers/api-key-providers.mdx:90— "Providers not listed here (Cerebras, NVIDIA NIM, AWS Bedrock, Kilo, OpenCode Zen) issue keys with no fixed prefix."ABSK(bedrock-region.tsAWS_BEARER_TOKEN_PREFIX, legacybedrock-api-key-); nvidia key prefix placeholdernvapi-. Prefixes are UI placeholders/branding, not enforced server-side.ABSK/nvapi-placeholder in the form.5 · [IMAGE] The "Add a provider" flow describes the Routing tile grid in words only
Page: https://manifest.build/docs/providers/api-key-providers ("Add a provider", the "Open the Routing page" step)
A screenshot of the Routing page tile grid belongs under the "Add a provider" steps.
Evidence (for the agent)
providers/api-key-providers.mdx:53-65— the three-step flow ("navigate to Routing... You'll see a tile for every supported provider") describes the tile grid with no image.6 · [IMAGE] The API Key vs Subscription two-tab panel is described but not shown
Page: https://manifest.build/docs/providers/subscription-based-providers ("Connect a subscription", the "Pick the Subscription tab" step)
A screenshot of a dual-auth provider panel showing the two tabs (API Key and Subscription) belongs under the "Pick the Subscription tab" step, so users see where the tab switch is before following the prose.
Evidence (for the agent)
providers/subscription-based-providers.mdx:41-45— "Providers that take either credential show two tabs (API Key and Subscription); pick Subscription."Reply with the finding number and the chosen option
(e.g. "3 → option 2", or "3: other idea, let's discuss").
PRs are then made manually with the agent, never by the harness.
Rejected findings: reply "N → reject" and they will never be re-raised.