Operators can now curate exactly which models `/v1/models` advertises via two
opt-in string-array settings, `modelVisibilityAllowlist`/`modelVisibilityDenylist`
(default empty = zero behavior change). Entries are exact "provider/model" (or
bare "model") ids, or a glob pattern via the existing shared globToRegex
matcher (src/shared/utils/globPattern.ts) already used by ModelRoutingSection
and freeModels.ts.
Follows the hidePaidModels/hideAutoCombos template (src/lib/db/settings.ts):
- src/shared/utils/modelExposureList.ts: the pure isModelExposureAllowed()
predicate (deny wins over allow; allow, when non-empty, restricts to it).
- src/app/api/v1/models/catalog.ts: wired at the same 5 per-source chokepoints
shouldHidePaid() already gates.
- open-sse/services/autoCombo/modelExposureFilter.ts +
virtualFactory.ts::buildPreparedPool: mandatory mirror into the auto/*
combo candidate pool, so a denied model can't be routed to via combo
selection either -- the exact trap #6512 already fixed once for
hidePaidModels.
- settingsSchemas.ts: Zod-validated (max 500 entries, 200 chars each).
config/quality/file-size-baseline.json: virtualFactory.ts is frozen with zero
headroom; bumped 1138->1144 for the minimal 2-line call-site wiring + import
(all real logic lives in the two new, unfrozen leaf modules).