Skip to content

feat: add citations to Bom for CycloneDX v1.7 - #1064

Open
juliosuas wants to merge 3 commits into
CycloneDX:mainfrom
juliosuas:feat/1.7-citations
Open

juliosuas wants to merge 3 commits into
CycloneDX:mainfrom
juliosuas:feat/1.7-citations

Conversation

@juliosuas

Copy link
Copy Markdown

Description

Adds support for the CycloneDX v1.7 citations element on the BOM.

  • New Citation model (cyclonedx/model/citation.py), covering bom-ref, pointers/expressions, timestamp, attributed-to, process and note.
  • Bom(citations=...): the citations are serialized only for schema version 1.7. Older schema versions leave them out.
  • 14 new snapshots for the JSON and XML outputs.
  • docs/schema-support.rst updated.

Refs #903

Out of scope (intentionally)

  • signature on citations
  • BomRefDiscriminator integration for citation bom-refs
  • CHANGELOG (left to the release tooling)

Testing

  • Full test suite: 7068 tests OK
  • flake8, isort and mypy: clean

AI disclosure

AI tools helped write this change. I reviewed and tested it before opening the PR.

Affirmation

  • My code follows the contributing guidelines
  • Commits are signed off (DCO)

Signed-off-by: juliosuas <juliosuas@users.noreply.github.com>
@codacy-production

Copy link
Copy Markdown

Up to standards ✅

🟢 Issues 0 issues

Results:
0 new issues

View in Codacy

🟢 Metrics 33 complexity · 0 duplication

Metric Results
Complexity 33
Duplication 0

View in Codacy

NEW Get contextual insights on your PRs based on Codacy's metrics, along with PR and Jira context, without leaving GitHub. Enable AI reviewer
TIP This summary will be updated as you push new changes.

@read-the-docs-community

read-the-docs-community Bot commented Nov 4, 2026 •

Copy link
Copy Markdown

Documentation build overview

📚 CycloneDX Python Library | 🛠️ Build #35900640 | 📁 Comparing 84f9085 against latest (5c873fa)

  🔍 Preview build  

5 files changed · + 1 added · ± 4 modified

+ Added

± Modified

@juliosuas
juliosuas marked this pull request as ready for review November 5, 2026 06:29
@juliosuas
juliosuas requested a review from a team as a code owner November 5, 2026 06:29

jkowalleck commented Nov 6, 2026 •

Copy link
Copy Markdown
Member

review done by Claude Fable 5.1, prompt: "do a review, comment your findings"


Verdict: LGTM with minor, non-blocking remarks.

What I verified

  • Schema conformance – Citation maps 1:1 to the 1.7 citationType (XSD) / #/definitions/citation (JSON): bom-ref attr, pointers⊕expressions choice, required timestamp, attributedTo/process (≥1), note. XML element order (xml_sequence 1–6) matches the XSD <xs:sequence>; bom.citations at sequence 120 lands after definitions (110), matching the root bom sequence.
  • Constraint handling – ctor correctly raises NoPropertiesProvidedException / MutuallyExclusivePropertiesException for the oneOf/anyOf rules, mirroring the schema's assertions.
  • Version gating – @serializable.view(SchemaVersion1Dot7) only; snapshots for 1.0–1.6 confirm citations are dropped there.
  • Snapshots – ran the 1.7 JSON and XML snapshots through JsonStrictValidator/XmlValidator: both valid.
  • Tests/lint – test_model_citation, test_output_{json,xml}, test_deserialize_{json,xml} (-k citation): 24 passed; flake8, isort, mypy clean on the touched files.
  • Conventions – __comparable_tuple/__lt__/__eq__/__hash__/__repr__, bom_ref_from_str, SortedSet setters and ignore_unknown_during_deserialization=True all follow the existing model style (e.g. Component, Vulnerability).

Minor remarks (non-blocking)

  1. BomRefDiscriminator.from_bom() (cyclonedx/contrib/bom/utils.py) still only collects component/service/vulnerability bom-refs. Citation bom-refs are therefore not de-duplicated against the rest of the BOM during output. You listed this as out of scope — fine, but it'd be good to open a follow-up issue so it isn't forgotten, since the XSD requires uniqueness across all elements.
  2. Setters bypass the ctor invariants – after construction one can do c.pointers = [] / c.attributed_to = None and end up with an object that no longer satisfies the schema. This is consistent with how other models in this lib behave (ctor-only checks), so just noting it.
  3. docs/schema-support.rst – other rows use Since ``x.y.z```; the new row says Since cyclonedx-python-lib ``next```. Consider aligning the wording (maintainers typically replace next at release time).
  4. Test fixture – get_bom_with_citations_1_7 only exercises attributed_to or process per citation; a case with both set would round-trip the full shape, but the unit tests already cover the constraint matrix, so optional.
  5. Docstring nit – module docstring says "Schema extension definition"; citations is a core 1.7 element, not an extension.

Nothing blocking from my side. 👍

@jkowalleck jkowalleck added enhancement New feature or request schema 1.7 labels Nov 6, 2026
self.expressions = expressions
self.timestamp = timestamp
self.attributed_to = attributed_to
self.process = process

@kmlyz kmlyz Nov 13, 2026 •

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

In cyclonedx/model/citation.py (Citation.__init__, lines 78-87), if attributed_to is None and process is None: runs before self.attributed_to and self.process are normalized via _bom_ref_from_str(..., optional=True). Passing attributed_to='' (or process='') bypasses NoPropertiesProvidedException and sets both fields to None, so JsonV1Dot7 emits a citation entry without attributedTo or process that fails JsonStrictValidator(SchemaVersion.V1_7). Passing an empty BomRef() similarly serializes attributedTo as None and causes Citation(..., attributed_to=BomRef(), process='p1') == Citation(..., attributed_to=None, process='p1') to evaluate to False. Assigning self.attributed_to and self.process before checking if not self.attributed_to and not self.process: keeps constructor validation and equality aligned with the 1.7 schema.

Disclosure: Review and test verification conducted with assistance from Gemini 4 Argon.

Signed-off-by: juliosuas <juliosuas@users.noreply.github.com>
Align the schema-support wording to "Since next", drop
"extension" from the Citation module docstring, and add a
fixture citation that sets both attributed_to and process.

Signed-off-by: juliosuas <juliosuas@users.noreply.github.com>

This branch has not been deployed

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

Labels

enhancement New feature or request schema 1.7

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants