Files
OmniRoute/tests/unit/model-exposure-list.test.ts
Diego Rodrigues de Sa e Souza 34e2f84c04 feat(api): explicit model exposure allow/deny list for /v1/models (#11481) (#11997)
Adds opt-in modelVisibilityAllowlist/modelVisibilityDenylist settings so an operator can curate exactly which models GET /v1/models advertises, mirrored into auto/* combo candidate pools (the same trap #6512 fixed for hidePaidModels). Default off, no behavior change for anyone who doesn't opt in.

TDD: 4 new test files, 22/22 passing (16 node:test + 6 vitest) + regression sweep across virtual-auto-combo/hide-paid/hide-auto-no-think suites (21/21).

Rebased onto the updated tip (a sibling #9133 landed first, same file) — kept both rebaseline annotations in file-size-baseline.json and set the value to the real measured line count after both merged.
2026-08-29 15:40:32 -03:00

80 lines
3.4 KiB
TypeScript

/**
* #11481 — explicit model exposure allow/deny list for `/v1/models` (and, via the
* mirror in `open-sse/services/autoCombo/modelExposureFilter.ts`, the `auto/*`
* candidate pool). Follows the `hidePaidModels`/`hideAutoCombos` opt-in shape
* (`src/lib/db/settings.ts`): default-off, two independent string arrays.
*
* Tests the pure predicate `isModelExposureAllowed()` — the single chokepoint
* both `catalog.ts` and the combo-pool mirror call into.
*/
import { test } from "node:test";
import assert from "node:assert/strict";
import { isModelExposureAllowed } from "@/shared/utils/modelExposureList";
test("default off (both lists empty) — every model is exposed", () => {
assert.equal(isModelExposureAllowed("openai", "gpt-4o", {}), true);
assert.equal(
isModelExposureAllowed("openai", "gpt-4o", {
modelVisibilityAllowlist: [],
modelVisibilityDenylist: [],
}),
true
);
assert.equal(isModelExposureAllowed("openai", "gpt-4o", null), true);
assert.equal(isModelExposureAllowed("openai", "gpt-4o", undefined), true);
});
test("denylist hides an exact-id match, leaves everything else exposed", () => {
const settings = { modelVisibilityDenylist: ["openai/gpt-4o"] };
assert.equal(isModelExposureAllowed("openai", "gpt-4o", settings), false);
assert.equal(isModelExposureAllowed("openai", "gpt-4o-mini", settings), true);
assert.equal(isModelExposureAllowed("anthropic", "claude-opus-5", settings), true);
});
test("denylist also matches the bare model id (no provider prefix required)", () => {
const settings = { modelVisibilityDenylist: ["gpt-4o"] };
assert.equal(isModelExposureAllowed("openai", "gpt-4o", settings), false);
});
test("allowlist restricts exposure to exactly the listed models", () => {
const settings = { modelVisibilityAllowlist: ["openai/gpt-4o-mini", "anthropic/claude-opus-5"] };
assert.equal(isModelExposureAllowed("openai", "gpt-4o-mini", settings), true);
assert.equal(isModelExposureAllowed("anthropic", "claude-opus-5", settings), true);
assert.equal(isModelExposureAllowed("openai", "gpt-4o", settings), false);
assert.equal(isModelExposureAllowed("google", "gemini-2.5-pro", settings), false);
});
test("denylist wins over allowlist for the same entry (deny is checked first)", () => {
const settings = {
modelVisibilityAllowlist: ["openai/gpt-4o"],
modelVisibilityDenylist: ["openai/gpt-4o"],
};
assert.equal(isModelExposureAllowed("openai", "gpt-4o", settings), false);
});
test("glob patterns are supported via the shared globToRegex matcher", () => {
const denyGlob = { modelVisibilityDenylist: ["openai/gpt-4*"] };
assert.equal(isModelExposureAllowed("openai", "gpt-4o", denyGlob), false);
assert.equal(isModelExposureAllowed("openai", "gpt-4.1", denyGlob), false);
assert.equal(isModelExposureAllowed("openai", "o1-preview", denyGlob), true);
const allowGlob = { modelVisibilityAllowlist: ["anthropic/*"] };
assert.equal(isModelExposureAllowed("anthropic", "claude-opus-5", allowGlob), true);
assert.equal(isModelExposureAllowed("openai", "gpt-4o", allowGlob), false);
});
test("non-array / malformed list values are treated as empty (fail open, never throw)", () => {
assert.equal(
isModelExposureAllowed("openai", "gpt-4o", {
modelVisibilityDenylist: "openai/gpt-4o" as unknown as string[],
}),
true
);
assert.equal(
isModelExposureAllowed("openai", "gpt-4o", {
modelVisibilityDenylist: [123 as unknown as string, " "],
}),
true
);
});