Background
ai-config's resolver merges several config sources with a fixed order (enforced > legacy-positron-enforced > env > user > legacy-positron > default), but the resolved output doesn't say which layer actually set a given field's value. ResolvedProvider.connectionProvenance exists, but it only covers two hardcoded special cases — Bedrock's aws.region and Snowflake's snowflake.connectionName — each with its own one-off shape. There's no general "which layer set field K on provider P" answer, and right now nothing outside ai-lib itself uses connectionProvenance.
This is blocking something concrete in Positron: a providers.custom entry with no matching record in the user's providers.json could be set by either default (should still be user-editable — typing in a new base URL should save) or enforced (correctly locked). Positron currently can't tell those two apart, so extensions/authentication/src/customProviderRegistry.ts's save handler treats them the same way (skips the write), which is too strict for the default case. Same gap for built-in providers: there's no way for Positron's UI to grey out a field because it's enforced, since nothing tells it that (positron.d.ts has no "locked" or "read-only" concept at all).
This came up in posit-dev/positron#15675.
Ask
add a general per-field (or at least per-provider) signal to the resolver output — surfaced on ResolvedProvider — that says which layer currently owns a given field's value, generalizing what connectionProvenance already does instead of adding more special cases per field.
Once this exists, customProviderRegistry.ts could treat default and enforced differently on save, and connectProviderView.tsx could grey out a base URL field when it's locked by enforced.
Background
ai-config's resolver merges several config sources with a fixed order (enforced > legacy-positron-enforced > env > user > legacy-positron > default), but the resolved output doesn't say which layer actually set a given field's value.
ResolvedProvider.connectionProvenanceexists, but it only covers two hardcoded special cases — Bedrock'saws.regionand Snowflake'ssnowflake.connectionName— each with its own one-off shape. There's no general "which layer set field K on provider P" answer, and right now nothing outside ai-lib itself usesconnectionProvenance.This is blocking something concrete in Positron: a
providers.customentry with no matching record in the user'sproviders.jsoncould be set by eitherdefault(should still be user-editable — typing in a new base URL should save) orenforced(correctly locked). Positron currently can't tell those two apart, soextensions/authentication/src/customProviderRegistry.ts's save handler treats them the same way (skips the write), which is too strict for thedefaultcase. Same gap for built-in providers: there's no way for Positron's UI to grey out a field because it's enforced, since nothing tells it that (positron.d.tshas no "locked" or "read-only" concept at all).This came up in posit-dev/positron#15675.
Ask
add a general per-field (or at least per-provider) signal to the resolver output — surfaced on
ResolvedProvider— that says which layer currently owns a given field's value, generalizing whatconnectionProvenancealready does instead of adding more special cases per field.Once this exists,
customProviderRegistry.tscould treatdefaultandenforceddifferently on save, andconnectProviderView.tsxcould grey out a base URL field when it's locked byenforced.