MemberJunction / MemberJunction/MJ

vwAIModels flattened APIName is a cross-vendor footgun: adding an AIModelVendor row can silently change every consumer's model id

Open
#3,066 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
TSQL
Stars
29
Forks
6
Avg merge
2d 1h
Merged PRs (30d)
323

Description

## Summary

`vwAIModels` flattens `APIName` to the single vendor row that wins the priority sort (`ORDER BY Priority DESC` as of v5.44). Any consumer that reads `Model.APIName` and hands it to a **specific** vendor's SDK is one metadata row away from breakage: adding a higher-priority `AIModelVendor` row for a different vendor silently swaps the id format for everyone.

## Real incident (2026-07-06)

- A model had a Google vendor row (`APIName='gemini-3.1-pro-preview'`, Priority 0).
- An OpenRouter vendor row was added (`APIName='google/gemini-3.1-pro-preview'`, Priority 50).
- After the v5.44 view change, the flattened `APIName` flipped to the OpenRouter format.
- A consumer that resolved the model id from `AIEngine.Instance.Models[].APIName` and called the `@google/genai` SDK directly began 404ing on every call (`models/google/gemini-3.1-pro-preview:generateContent`). Nothing in the model's own configuration had changed.

## The footgun

`APIName` only has meaning **relative to a vendor** (`AIModelVendor.APIName`), but the flattened view field presents it as a property of the model. There is no warning that its value depends on the priority ordering of unrelated vendor rows.

Our fix was to stop reading the flattened field and pin `{ modelId, vendorId }` via `AIPromptParams.override`, letting `AIPromptRunner` pair `APIName` + `DriverClass` + credentials from the same `AIModelVendor` row atomically — which is structurally immune. But other consumers (in MJ and downstream) may still read the flattened field.

## Suggestions (any of)

1. Document prominently (TSDoc on the generated entity field + view extended property) that `vwAIModels.APIName` is "highest-priority vendor's API name" and must not be fed to a vendor-specific SDK.
2. Audit MJ-internal consumers of the flattened `APIName` for the same pattern.
3. Longer term: expose API names only through vendor-scoped accessors (model+vendor pair) and deprecate the flattened field.

## Version

MJ v5.44.0

Contributor guide

Open the contributing guide

Research direction

Start with the vwAIModels view and the generated entity field for APIName; review how its Priority ordering selects a vendor value. Then inspect AIEngine.Instance.Models, AIPromptParams.override, and AIPromptRunner for consumers and vendor-pinned behavior. Done means the affected consumers are audited and the chosen documentation, accessor, or deprecation scope is agreed.

Written by the indexing model from the issue text.

Assessment

Tech stack
sql
Domain
ai, backend-api-design, database
Issue type
Bug
Difficulty
5/5
Estimated time
Over a week
Activity status
Quiet
Clarity
Needs clarification
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.