From b58d888d8481506b4d968ae12c29dbac4c5ccdc0 Mon Sep 17 00:00:00 2001 From: mlsmaycon Date: Thu, 27 Aug 2026 12:34:15 +0000 Subject: [PATCH] Surface catalog models in the scoped provider list for unrestricted callers An unrestricted policy on a provider without an operator declaration left the caller-scoped model list empty while the setup answer advertises the catalog models. The scoped list now always carries the effective set, so the dashboard's model filter matches the setup page in every shape. --- .../internals/modules/agentnetwork/manager.go | 18 ++++++------ .../agentnetwork/provider_redaction_test.go | 28 +++++++++++++++++++ 2 files changed, 38 insertions(+), 8 deletions(-) diff --git a/management/internals/modules/agentnetwork/manager.go b/management/internals/modules/agentnetwork/manager.go index f3dbcaf18..f1e119b12 100644 --- a/management/internals/modules/agentnetwork/manager.go +++ b/management/internals/modules/agentnetwork/manager.go @@ -254,14 +254,16 @@ func (m *managerImpl) callerScopedProviders(ctx context.Context, accountID, user for _, p := range authorized { r := p.RedactedForViewer() // The model list follows the same effective computation the setup - // answer and the proxy use: a caller whose policies carry a model - // allowlist sees only the models those guardrails permit, so the - // dashboard's model filter never offers a model the caller's own - // requests could not use. Grant holders keep the full declared - // lists — their usage view spans everyone's requests. - if allAllowed, effective := effectiveModelsForProvider(p, policiesForProvider(applicable, p.ID), guardrailsByID); !allAllowed { - r.Models = providerModelsByID(p, effective) - } + // answer and the proxy use: allowlist-restricted callers see only + // the models their guardrails permit, and an unrestricted policy + // on a provider without an operator declaration surfaces the + // catalog models, matching the setup response — so the dashboard's + // model filter never offers a model the caller's own requests + // could not use, and never comes up empty when the setup page + // lists models. Grant holders keep the full declared lists — + // their usage view spans everyone's requests. + _, effective := effectiveModelsForProvider(p, policiesForProvider(applicable, p.ID), guardrailsByID) + r.Models = providerModelsByID(p, effective) out = append(out, r) } return out, nil diff --git a/management/internals/modules/agentnetwork/provider_redaction_test.go b/management/internals/modules/agentnetwork/provider_redaction_test.go index e6a415c75..246f4db1e 100644 --- a/management/internals/modules/agentnetwork/provider_redaction_test.go +++ b/management/internals/modules/agentnetwork/provider_redaction_test.go @@ -259,3 +259,31 @@ func TestGetAllProviders_SelfScopedAllowlistWithoutDeclaredModels(t *testing.T) require.Len(t, scoped[0].Models, 1) assert.Equal(t, "gpt-5.4", scoped[0].Models[0].ID) } + +func TestGetAllProviders_SelfScopedUnrestrictedFallsBackToCatalogModels(t *testing.T) { + ctx := context.Background() + mgr, s := newSelfScopeStore(t) + + // Unrestricted policy on a provider without an operator declaration: + // the setup answer advertises the catalog models, and the scoped + // provider list must match so the model filter is never emptier than + // the setup page. + granted := newSynthTestProvider() + granted.ID = "prov-catalog" + granted.Name = "Granted" + granted.Models = nil + require.NoError(t, s.SaveAgentNetworkProvider(ctx, granted)) + policy := newSynthTestPolicy(granted.ID, "grp-eng", "") + policy.ID = "pol-catalog" + require.NoError(t, s.SaveAgentNetworkPolicy(ctx, policy)) + + scoped, err := mgr.GetAllProviders(ctx, testAccountID, "user-a") + require.NoError(t, err) + require.Len(t, scoped, 1) + require.NotEmpty(t, scoped[0].Models, "catalog models back the filter when the operator declared none") + ids := make([]string, 0, len(scoped[0].Models)) + for _, m := range scoped[0].Models { + ids = append(ids, m.ID) + } + assert.Equal(t, declaredModelIDs(granted), ids, "the scoped list mirrors the setup answer's declared/catalog set") +}