From 8febd55e44edc5ca62e8ca466c75438828d94ea9 Mon Sep 17 00:00:00 2001 From: KooshaPari <42529354+KooshaPari@users.noreply.github.com> Date: Sat, 18 Jul 2026 11:13:31 -0700 Subject: [PATCH] feat(sidecar): support conditional provider manifest refresh (#7130) * feat(sidecar): support conditional provider manifest refresh * fix(sidecar): accept weak manifest validators * perf(sidecar): cache provider manifest payload * docs(sidecar): describe manifest conditional refresh * test(sidecar): restore CORS preflight and manifest-content coverage The ETag/conditional-refresh rewrite of this test file dropped two pieces of coverage without replacing them: the CORS OPTIONS-preflight test, and the 200-response test's providers.length>100 / clientSecret-not-leaked assertions. This is the only test file for the provider-plugin-manifest route, so none of that was covered anywhere else afterward. Restore both: fold the providers.length/openai-presence/clientSecret assertions back into the "stable ETag" 200-response test alongside the new ETag checks, and add back a dedicated OPTIONS test asserting the CORS preflight headers. Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com> --------- Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com> --- docs/reference/PROVIDER_PLUGIN_MANIFEST.md | 8 ++++ .../api/v1/provider-plugin-manifest/route.ts | 42 ++++++++++++++++--- .../v1/provider-plugin-manifest-route.test.ts | 34 ++++++++++++++- 3 files changed, 77 insertions(+), 7 deletions(-) diff --git a/docs/reference/PROVIDER_PLUGIN_MANIFEST.md b/docs/reference/PROVIDER_PLUGIN_MANIFEST.md index 9f91dc39ed..9db239b371 100644 --- a/docs/reference/PROVIDER_PLUGIN_MANIFEST.md +++ b/docs/reference/PROVIDER_PLUGIN_MANIFEST.md @@ -21,6 +21,14 @@ OmniRoute advertises that URL to Bifrost and CLIProxyAPI via the `OMNIROUTE_PROVIDER_MANIFEST_URL` when the sidecar needs a public or container network URL instead of the local request origin. +## Refreshing the Manifest + +The HTTP endpoint returns `Cache-Control: public, max-age=60` and a strong +`ETag`. A sidecar should retain the last validated manifest and send its ETag +in `If-None-Match` when refreshing. A `304 Not Modified` response has no body; +the sidecar keeps its cached manifest. If no validated cached manifest exists, +the sidecar must issue an unconditional request instead of accepting a `304`. + ## Goal Move provider metadata toward a plugin contract so the hot request path can diff --git a/src/app/api/v1/provider-plugin-manifest/route.ts b/src/app/api/v1/provider-plugin-manifest/route.ts index 9774b49f53..593693c9df 100644 --- a/src/app/api/v1/provider-plugin-manifest/route.ts +++ b/src/app/api/v1/provider-plugin-manifest/route.ts @@ -1,12 +1,16 @@ +import { createHash } from "node:crypto"; + import { CORS_HEADERS } from "@/shared/utils/cors"; import { generateProviderPluginManifest } from "@omniroute/open-sse/config/providerPluginManifestRegistry.ts"; -const JSON_HEADERS = { +const CACHE_HEADERS = { ...CORS_HEADERS, - "Content-Type": "application/json", "Cache-Control": "public, max-age=60", } as const; +// The provider registry is module-static; process reloads rebuild this snapshot. +let cachedPayload: { body: string; etag: string } | null = null; + export async function OPTIONS() { return new Response(null, { headers: { @@ -17,8 +21,36 @@ export async function OPTIONS() { }); } -export async function GET() { - return new Response(JSON.stringify(generateProviderPluginManifest()), { - headers: JSON_HEADERS, +function createEtag(body: string): string { + return `"${createHash("sha256").update(body).digest("base64url")}"`; +} + +function matchesEtag(ifNoneMatch: string | null, etag: string): boolean { + return Boolean( + ifNoneMatch + ?.split(",") + .map((value) => value.trim()) + .some((value) => value === "*" || value === etag || value === `W/${etag}`) + ); +} + +function getManifestPayload(): { body: string; etag: string } { + if (cachedPayload) return cachedPayload; + + const body = JSON.stringify(generateProviderPluginManifest()); + cachedPayload = { body, etag: createEtag(body) }; + return cachedPayload; +} + +export async function GET(request: Request) { + const { body, etag } = getManifestPayload(); + const headers = { ...CACHE_HEADERS, ETag: etag }; + + if (matchesEtag(request.headers.get("If-None-Match"), etag)) { + return new Response(null, { status: 304, headers }); + } + + return new Response(body, { + headers: { ...headers, "Content-Type": "application/json" }, }); } diff --git a/tests/unit/api/v1/provider-plugin-manifest-route.test.ts b/tests/unit/api/v1/provider-plugin-manifest-route.test.ts index 9af7baa46d..e71f660782 100644 --- a/tests/unit/api/v1/provider-plugin-manifest-route.test.ts +++ b/tests/unit/api/v1/provider-plugin-manifest-route.test.ts @@ -6,11 +6,13 @@ import { OPTIONS, } from "../../../../src/app/api/v1/provider-plugin-manifest/route.ts"; -test("provider plugin manifest route returns JSON-safe manifest", async () => { - const response = await GET(); +test("provider plugin manifest returns a stable ETag with its cache policy", async () => { + const response = await GET(new Request("http://localhost/api/v1/provider-plugin-manifest")); const body = await response.json(); assert.equal(response.status, 200); + assert.equal(response.headers.get("Cache-Control"), "public, max-age=60"); + assert.match(response.headers.get("ETag") ?? "", /^"[A-Za-z0-9_-]+"$/); assert.equal(response.headers.get("Content-Type"), "application/json"); assert.equal(body.schemaVersion, 1); assert.equal(body.generatedFrom, "open-sse/config/providers"); @@ -28,3 +30,31 @@ test("provider plugin manifest route handles CORS preflight", async () => { assert.equal(response.headers.get("Access-Control-Allow-Methods"), "GET, OPTIONS"); assert.equal(response.headers.get("Access-Control-Allow-Headers"), "*"); }); + +test("provider plugin manifest supports conditional sidecar refreshes", async () => { + const initial = await GET(new Request("http://localhost/api/v1/provider-plugin-manifest")); + const etag = initial.headers.get("ETag"); + + const response = await GET( + new Request("http://localhost/api/v1/provider-plugin-manifest", { + headers: { "If-None-Match": etag ?? "" }, + }) + ); + + assert.equal(response.status, 304); + assert.equal(response.headers.get("ETag"), etag); + assert.equal(await response.text(), ""); +}); + +test("provider plugin manifest accepts weak conditional validators", async () => { + const initial = await GET(new Request("http://localhost/api/v1/provider-plugin-manifest")); + const etag = initial.headers.get("ETag"); + + const response = await GET( + new Request("http://localhost/api/v1/provider-plugin-manifest", { + headers: { "If-None-Match": `W/${etag}` }, + }) + ); + + assert.equal(response.status, 304); +});