Files
OmniRoute/tests/unit/model-exposure-list-settings-schema.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

64 lines
2.1 KiB
TypeScript

/**
* #11481 — `modelVisibilityAllowlist`/`modelVisibilityDenylist` settings PATCH
* schema validation. Mirrors hide-paid-models-settings-schema.test.ts.
*/
import test from "node:test";
import assert from "node:assert/strict";
import { updateSettingsSchema } from "../../src/shared/validation/settingsSchemas.ts";
test("modelVisibilityAllowlist/Denylist are accepted and preserved by the settings PATCH schema", () => {
const validation = updateSettingsSchema.safeParse({
modelVisibilityAllowlist: ["openai/gpt-4o-mini"],
modelVisibilityDenylist: ["openai/gpt-4o", "anthropic/*"],
});
assert.equal(validation.success, true);
if (!validation.success) return;
assert.deepEqual(validation.data.modelVisibilityAllowlist, ["openai/gpt-4o-mini"]);
assert.deepEqual(validation.data.modelVisibilityDenylist, ["openai/gpt-4o", "anthropic/*"]);
});
test("modelVisibilityAllowlist/Denylist default to undefined when not provided", () => {
const validation = updateSettingsSchema.safeParse({});
assert.equal(validation.success, true);
if (!validation.success) return;
assert.equal(validation.data.modelVisibilityAllowlist, undefined);
assert.equal(validation.data.modelVisibilityDenylist, undefined);
});
test("empty arrays (explicit opt-out / reset) are accepted", () => {
const validation = updateSettingsSchema.safeParse({
modelVisibilityAllowlist: [],
modelVisibilityDenylist: [],
});
assert.equal(validation.success, true);
});
test("rejects non-array values", () => {
assert.equal(
updateSettingsSchema.safeParse({ modelVisibilityDenylist: "openai/gpt-4o" }).success,
false
);
assert.equal(
updateSettingsSchema.safeParse({ modelVisibilityAllowlist: true }).success,
false
);
});
test("rejects a non-string array entry", () => {
assert.equal(
updateSettingsSchema.safeParse({ modelVisibilityDenylist: [123] }).success,
false
);
});
test("rejects an entry longer than the 200-char cap", () => {
assert.equal(
updateSettingsSchema.safeParse({ modelVisibilityDenylist: ["x".repeat(201)] }).success,
false
);
});