Skip to content

Latest commit

 

History

History
102 lines (81 loc) · 5.23 KB

File metadata and controls

102 lines (81 loc) · 5.23 KB

v1.1 technical route: Input and Policy Semantics

v1.1 narrows ambiguity at the two boundaries that CI consumers depend on: what an input parser actually supports, and why a policy decision was emitted. It does not add another scientific-computing mini-project or move the tool out of this monorepo.

Delivery status

Contract Current v1.1 status
Real input support matrix Implemented in parser-boundaries.md from the registered parsers
Policy schema identifier Implemented as sbom-diff-risk.policy.v1; legacy policy files remain readable
Report schema identifier and compatibility tests Implemented as sbom-diff-risk.report.v1 across checked-in full-report fixtures
Per-decision rule, evidence, reason, and confidence Implemented additively in report v1 policy finding objects
Component identity canonicalization Implemented as a typed value object with stable duplicate/conflict diagnostics
Ecosystem-specific canonicalization matrix Implemented in component-identity-canonicalization.md; package-name normalization is explicit per ecosystem rather than universal

Component identity contract

The canonical identity record will expose these dimensions separately:

  • ecosystem: trimmed and normalized to a registered ecosystem identifier.
  • package_name: normalized with ecosystem-aware rules. PyPI names use PEP 503 normalization; npm names use the packageurl-python npm purl name form; ecosystems without an explicit project rule preserve case rather than inheriting a universal lowercase rule.
  • version: trimmed but otherwise preserved as observed. The tool will not infer semantic equivalence between unrelated version schemes.
  • purl: parsed with packageurl-python and normalized when present, while retaining the observed purl in component evidence for auditability. An explicit component version does not get invented inside a versionless purl.
  • component_key: versionless package identity used to align before and after inputs. A version change remains a change, not an add plus remove.

Identity authority remains purl, then bom_ref, then the normalized (ecosystem, package_name) coordinate. A parseable purl is authoritative for its ecosystem and package coordinate. Explicit metadata that disagrees with that coordinate is a conflict, not an alternative identity.

Canonical identity also drives change comparison: lexical PyPI variants that normalize to the same identity do not create a metadata change, and a version change carried only by the purl is still classified as version_changed.

Within one input:

  • two records with the same key and identical normalized metadata fail closed as duplicate_component;
  • two records with the same key but different normalized metadata fail closed as conflicting_metadata;
  • conflicting ecosystem, package name, or version information between a purl and explicit fields also fails closed as conflicting_metadata;
  • an invalid purl also fails closed as conflicting_metadata because it cannot establish an unambiguous canonical identity;
  • metadata differences across the before and after inputs remain normal diff evidence and do not become same-input conflicts.

The implementation introduces a frozen CanonicalComponentIdentity object and keeps report presentation unchanged. The executable matrix is exposed through canonicalization_rules() so tests can assert the supported ecosystem rules. Tests cover CycloneDX-to-SPDX alignment, PyPI name normalization, case preservation for ecosystems without a declared name rule, namespace retention, versioned purls, exact duplicates, and conflicting metadata.

Policy and decision contract

policy_schema identifies the serialized policy family. The existing integer version continues to select rule capabilities and remains compatible with v1.0 policy files.

Every emitted policy finding includes:

  • matched_rule_id for the exact matching rule;
  • exact_evidence for the local values used in the comparison;
  • decision_reason as a stable machine-readable reason code;
  • confidence_level for the recorded evidence source.

The legacy rule_id, policy_rule, matched_threshold, and observed_value fields remain in report schema v1. Consumers can migrate to the grouped fields without a flag day.

Compatibility gate

Before v1.1 release:

  1. Every checked-in full JSON report must declare sbom-diff-risk.report.v1 and satisfy required-field/type tests.
  2. Every canonical policy example must declare sbom-diff-risk.policy.v1; legacy omission remains a tested compatibility path.
  3. Unknown policy schema identifiers must fail closed.
  4. Policy decisions in local, provenance, and Scorecard fixtures must expose rule, evidence, reason, and confidence fields.
  5. Existing v1.0 fields remain readable for the lifetime of report schema v1.

Repository boundary

sbom-diff-and-risk remains under tools/ in this monorepo for v1.1. Naming friction alone is not a migration trigger. A separate repository should be considered only after real third-party adoption creates an independent release cadence, issue stream, or packaging boundary. Production PyPI publishing is a separate decision and is not implied by this route.