[management] Check a vendor change, and bound the check by one deadline

Two gaps a review surfaced.

Moving a record from one catalog provider to another changed neither field the
check looked at, so an unchanged credential started being offered to a
different vendor, under a different auth header, with nothing asking whether it
was accepted there.

And each host lookup built its own eight-second budget from a background
context, so a slow resolver could spend one before the request spent another,
and a caller that gave up was still waiting. Bedrock made that three: it now
checks its runtime host as well. One deadline is taken at the top of Fetch and
carried through both lookups and the request.

The create description also had the exemption backwards, reading as though an
upstream the check cannot reach is stored unverified. Unreachable blocks; only
what cannot be checked at all is exempt.
This commit is contained in:
mlsmaycon
2026-08-26 14:23:58 +00:00
parent b64db1d587
commit 11faa925ee
5 changed files with 54 additions and 21 deletions
@@ -310,14 +310,20 @@ func (m *managerImpl) UpdateProvider(ctx context.Context, userID string, provide
return nil, status.Errorf(status.InvalidArgument, "api_key must be non-blank when rotating an agent network provider")
}
// Only the two fields the vendor would judge are worth a round-trip. This
// same call carries renames, model rows and price edits, and none of those
// Only the fields the vendor would judge are worth a round-trip. This same
// call carries renames, model rows and price edits, and none of those
// should wait on a vendor — or be refused because one is having a bad day.
//
// The catalog entry counts as one of them: it decides which vendor is
// asked, under which auth header, so moving a record from one to another
// sends an unchanged credential somewhere it has never been accepted.
//
// The comparison runs after the merge above, so an update that changes only
// the URL reads as unchanged on the key and is checked against the stored
// one, which is the only credential the operator has to offer here.
if provider.UpstreamURL != existing.UpstreamURL || provider.APIKey != existing.APIKey {
if provider.UpstreamURL != existing.UpstreamURL ||
provider.APIKey != existing.APIKey ||
provider.ProviderID != existing.ProviderID {
if err := m.checkProviderCredential(ctx, provider); err != nil {
return nil, err
}