Skip to content

Tracking: build and classify purls through one validated utils::purl API #748

Description

[agent] Filed by the scheduled architecture audit routine (CLI and core). Register: discussion #560 register.

Kind: tracking. Source: review 6.4, 7.3; register C20.

Problem (verified on 045d7ec)

utils/purl.rs has two builder families:

On top of these, 42 production format!("pkg:…") sites outside utils/purl.rs build purls by hand. The review counted 48; corrected here. The largest groups:

  • vex/product.rs: 13 sites, including versionless purls
  • vendor/path.rs::leaf_to_purl: 10
  • vendor/lock_inventory/recover.rs: 6
  • vex/discover/mod.rs: 5, with their own PyPI/composer/nuget canonicalization in discover/mod.rs L1455-L1468
  • hosted/engine.rs:622

There are also 24 inline starts_with("pkg:<type>/") checks beside Ecosystem::from_purl.

Drift already present. The families disagree on canonicalization:

  • composer_purl lowercases, while build_composer_purl, leaf_to_purl and recover.rs don't.
  • pypi_purl canonicalizes the name, while leaf_to_purl, recover.rs and the hosted skip purl (hosted/engine.rs:622) don't. vex::discover re-canonicalizes afterwards.
  • vlt.rs:290 alone percent-encodes the npm scope @.

Every consumer that compares purls therefore needs purl_eq/normalize_purl to paper over the differences.

Target design

  • utils::purl exposes one validated constructor per ecosystem (or Purl::new(Ecosystem, ns, name, version) -> Option<String>) that owns name canonicalization (PyPI PEP 503, composer and nuget lowercase), plus one versionless base_purl. build_* becomes private or is deleted.
  • Type checks go through Ecosystem::from_purl.

Checklist (one PR each, in order)

  • Route purl ecosystem checks through Ecosystem::from_purl instead of 24 inline starts_with("pkg:<type>/") tests #747: purl type checks through Ecosystem::from_purl (mechanical; can start now).
  • Vendored ledger keys (vendor/{gem,maven_repo,nuget_feed,composer_lock}.rs) and redirect/golang_local.rs move to the validated builders. An unsafe coordinate becomes a refusal instead of a ledger key. Owner: ecosystems area.
  • vendor/path.rs::leaf_to_purl and lock_inventory/recover.rs build through the validated builders, canonicalizing PyPI and composer once. Delete the re-canonicalization in vex::discover.
  • vex/product.rs versionless/product purls through one base_purl builder.
  • Delete the build_* family and purl_name_version, which only has a test caller.

Dependencies

No activity

Activity on this issue will appear here.

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

    agent:triagedarch-auditFiled by a scheduled architecture audit routine (see the architecture review discussion)priority:p3refactorStructural change: duplicated code or logic, missing abstraction, layering, dead code

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions