Skip to content

Conversation

@ahouseholder
Copy link
Contributor

@ahouseholder ahouseholder commented Jul 15, 2025

Selection Object

This PR adds a ssvc.selection module which contains a few pydantic dataclasses to represent a minimal version of an SSVC selection object. The MinimalSelectionList class is intended to serve as the source for a new JSON schema that replaces Decision_Point_Value_Selection_1-0-1.schema.json.

Our goal is to provide a terse object for data exchange purposes. To that end, the object does not represent fully-formed Decision Point objects, only the necessary fields to uniquely identify a specific decision point and its selected values. (A decision point is uniquely identified by its namespace, key, and version. Furthermore, within a given decision points, each value must have a unique value key. So the selection object only provides that level of detail. It's expected that in actual use, the receiver will dereference this selection object against a library of known decision point definitions.

Namespace Improvements

This PR also incorporates namespace improvements from #824

CoPilot Summary

This pull request introduces significant updates to the SSVC project, including the adoption of namespaces for SSVC objects, enhancements to schema definitions, and improvements to the codebase for better maintainability and functionality. The changes focus on enabling extensibility, improving schema validation, and refining documentation generation.

Namespace Implementation and Documentation:

  • Namespace Adoption for SSVC Objects: Added support for namespaces to distinguish between SSVC project objects and external objects, enabling customization and extensions. This includes registered namespaces for SSVC-maintained objects and unregistered namespaces for experimental or private use (docs/adr/0012-ssvc-namespaces.md, docs/adr/index.mdR26).
  • Namespace Validation: Updated _Namespaced mixin to use NamespaceString for stricter validation of namespace patterns (src/ssvc/_mixins.py, src/ssvc/_mixins.pyL73-R77).

Schema Enhancements:

Codebase Improvements:

  • Mixin Enhancements: Added _Timestamped mixin to automatically set timestamps for SSVC objects and updated _Versioned to use VersionString for semantic version validation (src/ssvc/_mixins.py, [1] [2].
  • Decision Point Enhancements: Introduced an id property for DecisionPoint to provide a unified identity string (src/ssvc/decision_points/base.py, src/ssvc/decision_points/base.pyR190-R197).
  • Documentation Improvements: Enhanced markdown generation for decision points by including object IDs in titles and examples (src/ssvc/doc_helpers.py, [1] [2].

Documentation and Tools:

  • Schema Dumping Utility: Added functionality to dump the SelectionList schema to a file for easier integration and validation (src/ssvc/doctools.py, [1] [2].
  • Decision Record Update: Included the new decision record for namespaces in the ADR index (docs/adr/index.md, docs/adr/index.mdR26).

These changes collectively improve the extensibility, validation, and usability of the SSVC framework while providing clear documentation and tools for developers and users.

Co-Pilot Schema Comparison

Based on review of the two schemas, here are the salient changes between version 1.0.1 and 2.0.0:

Schema Structure Changes

  • Title added: Version 2.0.0 includes a title field: "Decision Point Value Selection List"
  • Schema version: Updated from referencing external schema version to inline const: "2.0.0"
  • Additional properties: Both versions set additionalProperties: false at the root level

Property Changes

  • Removed properties:

    • id (vulnerability identifier) - replaced by target_ids
    • role (stakeholder role)
  • Added properties:

    • target_ids: Optional array of identifiers for items being evaluated (vulnerabilities, reports, etc.)
    • resources: Array of references providing context about decision points
    • references: Array of references providing context about selected values
  • Modified properties:

    • timestamp: Simplified to direct string format instead of referencing external definition
    • selections: Now uses internal Selection definition instead of external reference

Selection Object Changes

  • Restructured selection items: Moved from SsvcdecisionpointselectionSchema to simplified Selection object
  • New minimal approach: Selection objects are deliberately minimal and don't contain full decision point details
  • Enhanced namespace validation: Added complex regex pattern for namespace validation with support for locales and extensions
  • Version field: Added with default value "0.0.1" and semantic version validation
  • Values structure: Changed from simple string array to array of MinimalDecisionPointValue objects with key, name, and description fields

New Schema Definitions

  • MinimalDecisionPointValue: Minimal representation with key, name, and description
  • Reference: Structure for URI references with optional descriptions
  • Selection: Core selection object with namespace, key, version, and values

Required Fields Changes

  • Version 1.0.1 required: selections, id, timestamp, schemaVersion
  • Version 2.0.0 required: timestamp, schemaVersion, selections (removed id requirement)

@ahouseholder ahouseholder linked an issue Jul 15, 2025 that may be closed by this pull request
@ahouseholder ahouseholder requested a review from Copilot July 15, 2025 20:48
@ahouseholder ahouseholder self-assigned this Jul 15, 2025
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR introduces a new minimal SSVC selection model, aligns version strings to semantic format across CVSS groups, and adds a v2 JSON schema for selections.

  • Adds MinimalSelection and MinimalSelectionList Pydantic models with helper functions in src/ssvc/selection.py.
  • Standardizes all CVSS decision point group version fields to semantic X.Y.Z in collections.py.
  • Defines and references a new v2 JSON schema (Decision_Point_Value_Selection-2-0-0.schema.json) and updates the current schema pointer.

Reviewed Changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
src/test/decision_points/test_cvss_helpers.py Updated test data to use 1.0.0 instead of 1.0.
src/ssvc/selection.py New module defining minimal selection classes and schema generation.
src/ssvc/dp_groups/cvss/collections.py Bumped all CVSS group versions to semantic X.Y.Z.
src/ssvc/_mixins.py Introduced VersionField type for enforcing semantic version patterns.
data/schema/v2/Decision_Point_Value_Selection-2-0-0.schema.json Added v2 schema for selection objects with inline definitions.
data/schema/current/Decision_Point_Value_Selection.schema.json Updated current schema pointer to v2.
Comments suppressed due to low confidence (3)

src/ssvc/selection.py:90

  • The new add_selection method is not covered by any tests; consider adding unit tests to verify selections are appended correctly.
    def add_selection(self, selection: MinimalSelection) -> None:

src/ssvc/selection.py:100

  • The selection_from_decision_point conversion function lacks direct test coverage; adding tests will help ensure correct mapping from DecisionPoint to MinimalSelection.
def selection_from_decision_point(decision_point: DecisionPoint) -> MinimalSelection:

data/schema/v2/Decision_Point_Value_Selection-2-0-0.schema.json:131

  • The schema does not include additionalProperties: false, allowing arbitrary fields; consider adding it at the root to enforce strict validation.
  "type": "object",

@ahouseholder ahouseholder added integration/blocker Something that is blocking integration with another framework or system tech/backend Back-end tools, code, infrastructure integration Related to integration of SSVC into another framework or system labels Jul 15, 2025
@ahouseholder ahouseholder added this to the 2025-09 milestone Jul 15, 2025
@ahouseholder
Copy link
Contributor Author

@tschmidtb51 requesting your feedback on the new schema.

Copy link
Contributor

@tschmidtb51 tschmidtb51 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Careful - unfinished review]

All elements should have a minLength (for Strings) etc. attribute.

I'll finish my review tomorrow with a fresh set of eyes.

"title": "Version",
"type": "string"
},
"values": {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree with @sei-vsarvepalli that it is for humans nice to have a name value.

@tschmidtb51
Copy link
Contributor

Still reviewing

Copy link
Contributor

@tschmidtb51 tschmidtb51 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In my review, I came to the conclusion that it is best to use reverse FQDNs to differentiate between "language" and "xname" extensions. The latest and greatest is the new suggested ABNF - all other should follow from their or be made consistent to that...

Comment on lines +41 to +73
# --- Base namespace ---
NO_CONSECUTIVE_SEP = r"(?!.*[.-]{2,})" # no consecutive '.' or '-'

BASE_PATTERN = (
rf"{NO_CONSECUTIVE_SEP}"
r"[a-z][a-z0-9]+" # starts with lowercase letter + 1+ alnum
r"(?:[.-][a-z0-9]+)*" # optional dot or dash + alnum
)

BASE_NS_PATTERN = rf"(?:x_{BASE_PATTERN}|{BASE_PATTERN})"

# --- Extension segments ---
# A single ext-seg with at most one '#'
EXT_SEGMENT_PATTERN = (
rf"{NO_CONSECUTIVE_SEP}"
r"[a-zA-Z][a-zA-Z0-9]*" # start with a letter
r"(?:[.-][a-zA-Z0-9]+)*" # dot or dash + alnum
r"(?:#[a-zA-Z0-9]+(?:[.-][a-zA-Z0-9]+)*)?" # optional single hash section
)

# Subsequent ext-seg(s)
SUBSEQUENT_EXT = rf"{EXT_SEGMENT_PATTERN}(?:/{EXT_SEGMENT_PATTERN})*"


# --- Language extension ---
LANG_EXT = rf"(?:/{BCP_47_PATTERN}/|//)"

# --- Combine all parts into the full namespace pattern ---
NS_PATTERN_STR = (
rf"^{LENGTH_CHECK_PATTERN}"
rf"{BASE_NS_PATTERN}"
rf"(?:{LANG_EXT}{SUBSEQUENT_EXT})?$"
)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please see comment on ABNF

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mostly covered in the JSON file - but the interface is hung up - I can't comment anything here.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You might want to add some cases after changing the regex and ABNF.

@ahouseholder ahouseholder merged commit 9bcabec into main Jul 28, 2025
5 checks passed
@ahouseholder ahouseholder deleted the 820-add-a-minimalist-selection-object branch July 28, 2025 20:01
@ahouseholder
Copy link
Contributor Author

The ABNF and Regex commentary has gotten too complicated for me to track in the context of this PR, and absorbing all of it will require more attention than I can give it at the moment.

I've merged the PR at its current state.

Please consolidate the feedback into a concise issue focused on the regex constructor in ssvc.utils.patterns.NS_PATTERN. I can't keep reverse-engineering back from comments on JSON schema, through pydantic generators, into what to change in the python code. If pydantic doesn't do it out of the box, I'm not inclined to go further than that as it's hard to justify additional engineering time on this already.

As it stands, I currently regret bringing ABNF into it, as it's not something we can easily manage and generate, and am more inclined to remove it from the documentation than to revise it.

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

Labels

integration/blocker Something that is blocking integration with another framework or system integration Related to integration of SSVC into another framework or system tech/backend Back-end tools, code, infrastructure

Projects

None yet

4 participants