Skip to content

Bug: catalog search can return a shadowed lower-precedence entry that install never uses #3330

Closed

Description

@Quratulain-bilal

summary

specify integration search (via CatalogStack.search()) can return a bundle entry from a lower-precedence catalog even when a higher-precedence catalog defines the same bundle id. resolve()/install always use the higher-precedence entry, so search advertises a name/version/source the user can never actually install.

root cause

src/specify_cli/bundler/services/catalog_stack.py, search():

for source in self._sources:               # highest precedence first
    for bundle_id, entry in self._entries_for(source).items():
        if bundle_id in seen:
            continue
        if needle and not _matches(entry, needle):   # <-- id NOT claimed on a non-match
            continue
        seen[bundle_id] = ResolvedBundle(...)

an id is only added to seen when its entry matches the query. so if the highest-precedence entry for an id does not match, the id stays unclaimed, and a lower-precedence entry with the same id can match on a later iteration and be returned. that contradicts the docstring ("Each bundle id appears once, resolved at its highest-precedence source") and disagrees with resolve().

reproduction

bundle id shared exists in two catalogs — high-precedence (name "Alpha Tool") and low-precedence (name "Searchable Widget"):

  • resolve("shared") -> high-precedence entry (Alpha Tool)
  • search("widget") -> returns the low-precedence "Searchable Widget" entry, which install would never use

impact

search results can misrepresent a shadowed bundle: wrong name, version, author, and source catalog versus what install actually resolves. a user searching by a term that only matches the shadowed copy sees an entry they cannot install as shown.

proposed fix

resolve each id to its highest-precedence entry first, then filter the resolved set by the query. search then agrees with resolve(): a query matching only a shadowed lower-precedence copy returns nothing.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions