roleKeyNames function

Set<String> roleKeyNames(
  1. ModelRolesConfig rolesConfig, {
  2. List<CustomProviderEntry> customProviders = const [],
})

The explicit apiKeyNames referenced by a roles config (the secure-store preload set; the catalog names are always preloaded), plus the endpoint-scoped FA_KEY_<HOST> slot of every chain entry pinned to a custom endpoint (gh-1000 AC5 — the same source a manual provider switch resolves; the catalog env names describe default endpoints only). customProviders mirrors the resolver's registry leg (issue #1552): a catalog-unknown ref that names one of these entries resolves its default endpoint from the entry, so an explicit ref baseUrl over a custom entry is a non-default pin the same way.

Implementation

Set<String> roleKeyNames(
  ModelRolesConfig rolesConfig, {
  List<CustomProviderEntry> customProviders = const [],
}) {
  final refs = _rolesChainRefs(rolesConfig);
  return {
    for (final ref in refs) ...[
      if (ref.apiKeyName != null) ref.apiKeyName!,
      // gh-1570 incident REG: the resolver's fallbacks probe the whole
      // cross-version slot family, so the snapshot must carry it — the
      // endpoint-scoped candidates of every custom-endpoint ref (the
      // unpinned leg, mirroring ModelRolesResolver
      // ._endpointScopedKeyNames exactly) plus, for an explicitly pinned
      // ref, the pin's own endpoint family (the empty-pin fallback set —
      // the 1.0.556 → 1.0.564 lockout shape). The unpinned leg keeps the
      // issue #1552 customProviders mirror (see the doc comment above):
      // an unknown provider naming a custom entry resolves its spec
      // through the entry.
      if (_refNeedsEndpointSlot(ref, customProviders))
        ...CustomProviderRegistry.keySlotCandidates(ref.baseUrl!),
      if (ref.apiKeyName != null && ref.baseUrl != null)
        ...CustomProviderRegistry.keySlotCandidates(ref.baseUrl!),
    ],
  };
}