Repository: CycloneDX/cyclonedx-rust-cargo (language: rust)

Issue:
cyclonedx_bom: make Cpe constructable
The current implementation of Cpe in https://github.com/CycloneDX/cyclonedx-rust-cargo/blob/main/cyclonedx-bom/src/models/component.rs does not allow access to the member variable and provides no constructors. Some way to construct Cpes in applications which use the bom library should be provided.

eg.:
`let cpe = Cpe(cpe_string);`

Result:

```
note: constructor is not visible here due to private fields
   --> /home/scott/.cargo/registry/src/index.crates.io-6f17d22bba15001f/cyclonedx-bom-0.4.3/src/models/component.rs:439:16
    |
439 | pub struct Cpe(pub(crate) String);
    |                ^^^^^^^^^^^^^^^^^ private field
```

    
We can implement, if you let us know if you prefer public member variable, a `new `constructor or conversion from `String `or `&str`, etc. Purl, for instance implements both `new `and `FromStr`


Discussion / hints:
Having both `new()` and `FromStr` sounds good to me. I'd be happy to merge a PR with this change.
Ok, will do. But I need some time because I'm working on something else right now. Thanks!

Fix patch:
diff --git a/cyclonedx-bom/src/models/annotation.rs b/cyclonedx-bom/src/models/annotation.rs
index 4f2641ae..531c6bd1 100644
--- a/cyclonedx-bom/src/models/annotation.rs
+++ b/cyclonedx-bom/src/models/annotation.rs
@@ -45,12 +45,12 @@ impl Validate for Annotations {
 
 #[derive(Clone, Debug, PartialEq, Eq)]
 pub struct Annotation {
-    pub(crate) bom_ref: Option<String>,
-    pub(crate) subjects: Vec<String>,
-    pub(crate) annotator: Annotator,
-    pub(crate) timestamp: DateTime,
-    pub(crate) text: String,
-    pub(crate) signature: Option<Signature>,
+    pub bom_ref: Option<String>,
+    pub subjects: Vec<String>,
+    pub annotator: Annotator,
+    pub timestamp: DateTime,
+    pub text: String,
+    pub signature: Option<Signature>,
 }
 
 impl Validate for Annotation {
diff --git a/cyclonedx-bom/src/models/attached_text.rs b/cyclonedx-bom/src/models/attached_text.rs
index 46d085b9..290072cd 100644
--- a/cyclonedx-bom/src/models/attached_text.rs
+++ b/cyclonedx-bom/src/models/attached_text.rs
@@ -27,9 +27,9 @@ use super::bom::SpecVersion;
 
 #[derive(Clone, Debug, PartialEq, Eq, Hash)]
 pub struct AttachedText {
-    pub(crate) content_type: Option<NormalizedString>,
-    pub(crate) encoding: Option<Encoding>,
-    pub(crate) content: String,
+    pub content_type: Option<NormalizedString>,
+    pub encoding: Option<Encoding>,
+    pub content: String,
 }
 
 impl AttachedText {
@@ -74,7 +74,7 @@ impl Validate for AttachedText {
 }
 
 /// Function to check [`Encoding`].
-pub(crate) fn validate_encoding(encoding: &Encoding) -> Result<(), ValidationError> {
+pub fn validate_encoding(encoding: &Encoding) -> Result<(), ValidationError> {
     if matches!(encoding, Encoding::UnknownEncoding(_)) {
         return Err(ValidationError::new("Unknown encoding"));
     }
@@ -83,7 +83,7 @@ pub(crate) fn validate_encoding(encoding: &Encoding) -> Result<(), ValidationErr
 
 #[derive(Clone, Debug, PartialEq, Eq, strum::Display, Hash)]
 #[strum(serialize_all = "kebab-case")]
-pub(crate) enum Encoding {
+pub enum Encoding {
     Base64,
     #[doc(hidden)]
     #[strum(default)]
@@ -91,7 +91,7 @@ pub(crate) enum Encoding {
 }
 
 impl Encoding {
-    pub(crate) fn new_unchecked<A: AsRef<str>>(value: A) -> Self {
+    pub fn new_unchecked<A: AsRef<str>>(value: A) -> Self {
         match value.as_ref() {
             "base64" => Self::Base64,
             unknown => Self::UnknownEncoding(unknown.to_string()),
diff --git a/cyclonedx-bom/src/models/bom.rs b/cyclonedx-bom/src/models/bom.rs
index c05b0993..f0e72acc 100644
--- a/cyclonedx-bom/src/models/bom.rs
+++ b/cyclonedx-bom/src/models/bom.rs
@@ -79,7 +79,7 @@ impl FromStr for SpecVersion {
     }
 }
 
-pub(crate) fn validate_bom_ref(
+pub fn validate_bom_ref(
     _bom_ref: &BomReference,
     version: SpecVersion,
 ) -> Result<(), ValidationError> {
@@ -91,7 +91,7 @@ pub(crate) fn validate_bom_ref(
 
 /// A reference to a Bom element
 #[derive(Clone, Debug, PartialEq, Eq, Hash)]
-pub struct BomReference(pub(crate) String);
+pub struct BomReference(pub String);
 
 impl BomReference {
     pub fn new<T>(input: T) -> Self
@@ -576,7 +576,7 @@ fn validate_vulnerabilities_bom_refs(
 }
 
 #[derive(Clone, Debug, PartialEq, Eq)]
-pub struct UrnUuid(pub(crate) String);
+pub struct UrnUuid(pub String);
 
 impl UrnUuid {
     pub fn new(value: String) -> Result<Self, UrnUuidError> {
diff --git a/cyclonedx-bom/src/models/code.rs b/cyclonedx-bom/src/models/code.rs
index b17a8569..de093619 100644
--- a/cyclonedx-bom/src/models/code.rs
+++ b/cyclonedx-bom/src/models/code.rs
@@ -147,7 +147,7 @@ pub enum IssueClassification {
 }
 
 impl IssueClassification {
-    pub(crate) fn new_unchecked<A: AsRef<str>>(value: A) -> Self {
+    pub fn new_unchecked<A: AsRef<str>>(value: A) -> Self {
         match value.as_ref() {
             "defect" => Self::Defect,
             "enhancement" => Self::Enhancement,
@@ -216,7 +216,7 @@ pub enum PatchClassification {
 }
 
 impl PatchClassification {
-    pub(crate) fn new_unchecked<A: AsRef<str>>(value: A) -> Self {
+    pub fn new_unchecked<A: AsRef<str>>(value: A) -> Self {
         match value.as_ref() {
             "unofficial" => Self::Unofficial,
             "monkey" => Self::Monkey,
diff --git a/cyclonedx-bom/src/models/component.rs b/cyclonedx-bom/src/models/component.rs
index 937dbf21..7c70e8fa 100644
--- a/cyclonedx-bom/src/models/component.rs
+++ b/cyclonedx-bom/src/models/component.rs
@@ -218,7 +218,7 @@ pub enum Classification {
 }
 
 impl Classification {
-    pub(crate) fn new_unchecked<A: AsRef<str>>(value: A) -> Self {
+    pub fn new_unchecked<A: AsRef<str>>(value: A) -> Self {
         match value.as_ref() {
             "application" => Self::Application,
             "framework" => Self::Framework,
@@ -256,7 +256,7 @@ pub enum Scope {
 }
 
 impl Scope {
-    pub(crate) fn new_unchecked<A: AsRef<str>>(value: A) -> Self {
+    pub fn new_unchecked<A: AsRef<str>>(value: A) -> Self {
         match value.as_ref() {
             "required" => Self::Required,
             "optional" => Self::Optional,
@@ -281,7 +281,7 @@ pub fn validate_mime_type(mime_type: &MimeType) -> Result<(), ValidationError> {
 }
 
 #[derive(Clone, Debug, PartialEq, Eq, Hash)]
-pub struct MimeType(pub(crate) String);
+pub struct MimeType(pub String);
 
 #[derive(Clone, Debug, PartialEq, Eq, Hash)]
 pub struct Swid {
@@ -322,6 +322,24 @@ pub fn validate_cpe(cpe: &Cpe) -> Result<(), ValidationError> {
 #[derive(Clone, Debug, PartialEq, Eq, Hash)]
 pub struct Cpe(pub(crate) String);
 
+impl Cpe {
+    pub fn new(inner: &str) -> Self {
+        Self(inner.to_string())
+    }
+}
+
+impl From<String> for Cpe {
+    fn from(value: String) -> Self {
+        Self(value)
+    }
+}
+
+impl AsRef<String> for Cpe {
+    fn as_ref(&self) -> &String {
+        &self.0
+    }
+}
+
 impl AsRef<str> for Cpe {
     fn as_ref(&self) -> &str {
         &self.0
@@ -513,7 +531,7 @@ pub enum IdentityField {
 }
 
 impl IdentityField {
-    pub(crate) fn new_unchecked<A: AsRef<str>>(value: A) -> Self {
+    pub fn new_unchecked<A: AsRef<str>>(value: A) -> Self {
         match value.as_ref() {
             "group" => Self::Group,
             "name" => Self::Name,
@@ -593,7 +611,7 @@ pub fn validate_copyright(_copyright: &Copyright) -> Result<(), ValidationError>
 pub struct Copyright(pub String);
 
 #[derive(Clone, Debug, PartialEq, Eq, Hash)]
-pub struct CopyrightTexts(pub(crate) Vec<Copyright>);
+pub struct CopyrightTexts(pub Vec<Copyright>);
 
 impl Validate for CopyrightTexts {
     fn validate_version(&self, _version: SpecVersion) -> ValidationResult {
diff --git a/cyclonedx-bom/src/models/composition.rs b/cyclonedx-bom/src/models/composition.rs
index aa50e332..c6484768 100644
--- a/cyclonedx-bom/src/models/composition.rs
+++ b/cyclonedx-bom/src/models/composition.rs
@@ -98,7 +98,7 @@ pub enum AggregateType {
 }
 
 impl AggregateType {
-    pub(crate) fn new_unchecked<A: AsRef<str>>(value: A) -> Self {
+    pub fn new_unchecked<A: AsRef<str>>(value: A) -> Self {
         match value.as_ref() {
             "complete" => Self::Complete,
             "incomplete" => Self::Incomplete,
diff --git a/cyclonedx-bom/src/models/external_reference.rs b/cyclonedx-bom/src/models/external_reference.rs
index 1adb7ffd..24cb3c25 100644
--- a/cyclonedx-bom/src/models/external_reference.rs
+++ b/cyclonedx-bom/src/models/external_reference.rs
@@ -145,7 +145,7 @@ pub enum ExternalReferenceType {
 }
 
 impl ExternalReferenceType {
-    pub(crate) fn new_unchecked<A: AsRef<str>>(value: A) -> Self {
+    pub fn new_unchecked<A: AsRef<str>>(value: A) -> Self {
         match value.as_ref() {
             "vcs" => Self::Vcs,
             "issue-tracker" => Self::IssueTracker,
@@ -226,7 +226,7 @@ impl std::fmt::Display for Uri {
 }
 
 #[derive(Clone, Debug, PartialEq, Eq, Hash)]
-pub struct BomLink(pub(crate) String);
+pub struct BomLink(pub String);
 
 fn validate_bom_link(bom_link: &BomLink, version: SpecVersion) -> Result<(), ValidationError> {
     if version < SpecVersion::V1_5 {
diff --git a/cyclonedx-bom/src/models/formulation/mod.rs b/cyclonedx-bom/src/models/formulation/mod.rs
index 5ea1c844..30c560ba 100644
--- a/cyclonedx-bom/src/models/formulation/mod.rs
+++ b/cyclonedx-bom/src/models/formulation/mod.rs
@@ -11,11 +11,11 @@ use super::{bom::BomReference, component::Components, property::Properties, serv
 
 #[derive(PartialEq, Eq, Clone, Debug)]
 pub struct Formula {
-    pub(crate) bom_ref: Option<BomReference>,
-    pub(crate) components: Option<Components>,
-    pub(crate) services: Option<Services>,
-    pub(crate) workflows: Option<Vec<Workflow>>,
-    pub(crate) properties: Option<Properties>,
+    pub bom_ref: Option<BomReference>,
+    pub components: Option<Components>,
+    pub services: Option<Services>,
+    pub workflows: Option<Vec<Workflow>>,
+    pub properties: Option<Properties>,
 }
 
 impl Validate for Formula {
diff --git a/cyclonedx-bom/src/models/formulation/workflow/input.rs b/cyclonedx-bom/src/models/formulation/workflow/input.rs
index 0d286f08..d00479d0 100644
--- a/cyclonedx-bom/src/models/formulation/workflow/input.rs
+++ b/cyclonedx-bom/src/models/formulation/workflow/input.rs
@@ -7,11 +7,11 @@ use crate::{
 use super::{resource_reference::ResourceReference, EnvironmentVar};
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub(crate) struct Input {
-    pub(crate) required: RequiredInputField,
-    pub(crate) source: Option<ResourceReference>,
-    pub(crate) target: Option<ResourceReference>,
-    pub(crate) properties: Option<Properties>,
+pub struct Input {
+    pub required: RequiredInputField,
+    pub source: Option<ResourceReference>,
+    pub target: Option<ResourceReference>,
+    pub properties: Option<Properties>,
 }
 
 impl Validate for Input {
@@ -39,7 +39,7 @@ impl Validate for Input {
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub(crate) enum RequiredInputField {
+pub enum RequiredInputField {
     Resource(ResourceReference),
     Parameters(Vec<Parameter>),
     EnvironmentVars(Vec<EnvironmentVar>),
@@ -47,8 +47,8 @@ pub(crate) enum RequiredInputField {
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub(crate) struct Parameter {
-    pub(crate) name: Option<String>,
-    pub(crate) value: Option<String>,
-    pub(crate) data_type: Option<String>,
+pub struct Parameter {
+    pub name: Option<String>,
+    pub value: Option<String>,
+    pub data_type: Option<String>,
 }
diff --git a/cyclonedx-bom/src/models/formulation/workflow/mod.rs b/cyclonedx-bom/src/models/formulation/workflow/mod.rs
index 8483c3f3..a7059039 100644
--- a/cyclonedx-bom/src/models/formulation/workflow/mod.rs
+++ b/cyclonedx-bom/src/models/formulation/workflow/mod.rs
@@ -18,24 +18,24 @@ use self::{
 };
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub(crate) struct Workflow {
-    pub(crate) bom_ref: BomReference,
-    pub(crate) uid: String,
-    pub(crate) name: Option<String>,
-    pub(crate) description: Option<String>,
-    pub(crate) resource_references: Option<Vec<ResourceReference>>,
-    pub(crate) tasks: Option<Vec<Task>>,
-    pub(crate) task_dependencies: Option<Vec<Dependency>>,
-    pub(crate) task_types: Vec<TaskType>,
-    pub(crate) trigger: Option<Trigger>,
-    pub(crate) steps: Option<Vec<Step>>,
-    pub(crate) inputs: Option<Vec<Input>>,
-    pub(crate) outputs: Option<Vec<Output>>,
-    pub(crate) time_start: Option<DateTime>,
-    pub(crate) time_end: Option<DateTime>,
-    pub(crate) workspaces: Option<Vec<Workspace>>,
-    pub(crate) runtime_topology: Option<Vec<Dependency>>,
-    pub(crate) properties: Option<Properties>,
+pub struct Workflow {
+    pub bom_ref: BomReference,
+    pub uid: String,
+    pub name: Option<String>,
+    pub description: Option<String>,
+    pub resource_references: Option<Vec<ResourceReference>>,
+    pub tasks: Option<Vec<Task>>,
+    pub task_dependencies: Option<Vec<Dependency>>,
+    pub task_types: Vec<TaskType>,
+    pub trigger: Option<Trigger>,
+    pub steps: Option<Vec<Step>>,
+    pub inputs: Option<Vec<Input>>,
+    pub outputs: Option<Vec<Output>>,
+    pub time_start: Option<DateTime>,
+    pub time_end: Option<DateTime>,
+    pub workspaces: Option<Vec<Workspace>>,
+    pub runtime_topology: Option<Vec<Dependency>>,
+    pub properties: Option<Properties>,
 }
 
 impl Validate for Workflow {
@@ -81,22 +81,22 @@ impl Validate for Workflow {
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub(crate) struct Task {
-    pub(crate) bom_ref: BomReference,
-    pub(crate) uid: String,
-    pub(crate) name: Option<String>,
-    pub(crate) description: Option<String>,
-    pub(crate) resource_references: Option<Vec<ResourceReference>>,
-    pub(crate) task_types: Vec<TaskType>,
-    pub(crate) trigger: Option<Trigger>,
-    pub(crate) steps: Option<Vec<Step>>,
-    pub(crate) inputs: Option<Vec<Input>>,
-    pub(crate) outputs: Option<Vec<Output>>,
-    pub(crate) time_start: Option<DateTime>,
-    pub(crate) time_end: Option<DateTime>,
-    pub(crate) workspaces: Option<Vec<Workspace>>,
-    pub(crate) runtime_topology: Option<Vec<Dependency>>,
-    pub(crate) properties: Option<Properties>,
+pub struct Task {
+    pub bom_ref: BomReference,
+    pub uid: String,
+    pub name: Option<String>,
+    pub description: Option<String>,
+    pub resource_references: Option<Vec<ResourceReference>>,
+    pub task_types: Vec<TaskType>,
+    pub trigger: Option<Trigger>,
+    pub steps: Option<Vec<Step>>,
+    pub inputs: Option<Vec<Input>>,
+    pub outputs: Option<Vec<Output>>,
+    pub time_start: Option<DateTime>,
+    pub time_end: Option<DateTime>,
+    pub workspaces: Option<Vec<Workspace>>,
+    pub runtime_topology: Option<Vec<Dependency>>,
+    pub properties: Option<Properties>,
 }
 
 impl Validate for Task {
@@ -137,7 +137,7 @@ impl Validate for Task {
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash, strum::Display)]
 #[strum(serialize_all = "kebab-case")]
-pub(crate) enum TaskType {
+pub enum TaskType {
     Copy,
     Clone,
     Lint,
@@ -155,7 +155,7 @@ pub(crate) enum TaskType {
 }
 
 impl TaskType {
-    pub(crate) fn new_unchecked<S: AsRef<str>>(s: S) -> Self {
+    pub fn new_unchecked<S: AsRef<str>>(s: S) -> Self {
         match s.as_ref() {
             "copy" => Self::Copy,
             "clone" => Self::Clone,
@@ -188,7 +188,7 @@ impl Validate for TaskType {
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub(crate) enum EnvironmentVar {
+pub enum EnvironmentVar {
     Property { name: String, value: String },
     Value(String),
 }
diff --git a/cyclonedx-bom/src/models/formulation/workflow/output.rs b/cyclonedx-bom/src/models/formulation/workflow/output.rs
index 82c0bd2f..a610f7d7 100644
--- a/cyclonedx-bom/src/models/formulation/workflow/output.rs
+++ b/cyclonedx-bom/src/models/formulation/workflow/output.rs
@@ -7,12 +7,12 @@ use crate::{
 use super::{resource_reference::ResourceReference, EnvironmentVar};
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub(crate) struct Output {
-    pub(crate) required: RequiredOutputField,
-    pub(crate) r#type: Option<Type>,
-    pub(crate) source: Option<ResourceReference>,
-    pub(crate) target: Option<ResourceReference>,
-    pub(crate) properties: Option<Properties>,
+pub struct Output {
+    pub required: RequiredOutputField,
+    pub r#type: Option<Type>,
+    pub source: Option<ResourceReference>,
+    pub target: Option<ResourceReference>,
+    pub properties: Option<Properties>,
 }
 
 impl Validate for Output {
@@ -41,7 +41,7 @@ impl Validate for Output {
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub(crate) enum RequiredOutputField {
+pub enum RequiredOutputField {
     Resource(ResourceReference),
     EnvironmentVars(Vec<EnvironmentVar>),
     Data(Attachment),
@@ -49,7 +49,7 @@ pub(crate) enum RequiredOutputField {
 
 #[derive(Debug, Clone, strum::Display, PartialEq, Eq, Hash)]
 #[strum(serialize_all = "kebab-case")]
-pub(crate) enum Type {
+pub enum Type {
     Artifact,
     Attestation,
     Log,
@@ -62,7 +62,7 @@ pub(crate) enum Type {
 }
 
 impl Type {
-    pub(crate) fn new_unchecked<S: AsRef<str>>(s: S) -> Self {
+    pub fn new_unchecked<S: AsRef<str>>(s: S) -> Self {
         match s.as_ref() {
             "artifact" => Self::Artifact,
             "attestation" => Self::Attestation,
diff --git a/cyclonedx-bom/src/models/formulation/workflow/resource_reference.rs b/cyclonedx-bom/src/models/formulation/workflow/resource_reference.rs
index d2933658..42bb3389 100644
--- a/cyclonedx-bom/src/models/formulation/workflow/resource_reference.rs
+++ b/cyclonedx-bom/src/models/formulation/workflow/resource_reference.rs
@@ -3,7 +3,7 @@ use crate::{
 };
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub(crate) enum ResourceReference {
+pub enum ResourceReference {
     Ref(String),
     ExternalReference(ExternalReference),
 }
diff --git a/cyclonedx-bom/src/models/formulation/workflow/step.rs b/cyclonedx-bom/src/models/formulation/workflow/step.rs
index d9cf22ad..112e9d91 100644
--- a/cyclonedx-bom/src/models/formulation/workflow/step.rs
+++ b/cyclonedx-bom/src/models/formulation/workflow/step.rs
@@ -2,10 +2,10 @@ use crate::{models::property::Properties, prelude::Validate, validation::Validat
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
 pub struct Step {
-    pub(crate) commands: Option<Vec<Command>>,
-    pub(crate) description: Option<String>,
-    pub(crate) name: Option<String>,
-    pub(crate) properties: Option<Properties>,
+    pub commands: Option<Vec<Command>>,
+    pub description: Option<String>,
+    pub name: Option<String>,
+    pub properties: Option<Properties>,
 }
 
 impl Validate for Step {
@@ -24,8 +24,8 @@ impl Validate for Step {
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
 pub struct Command {
-    pub(crate) executed: Option<String>,
-    pub(crate) properties: Option<Properties>,
+    pub executed: Option<String>,
+    pub properties: Option<Properties>,
 }
 
 impl Validate for Command {
diff --git a/cyclonedx-bom/src/models/formulation/workflow/trigger.rs b/cyclonedx-bom/src/models/formulation/workflow/trigger.rs
index 9ec17196..61fad3f2 100644
--- a/cyclonedx-bom/src/models/formulation/workflow/trigger.rs
+++ b/cyclonedx-bom/src/models/formulation/workflow/trigger.rs
@@ -12,19 +12,19 @@ use crate::{
 use super::{input::Input, output::Output, resource_reference::ResourceReference};
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub(crate) struct Trigger {
-    pub(crate) bom_ref: BomReference,
-    pub(crate) uid: String,
-    pub(crate) name: Option<String>,
-    pub(crate) description: Option<String>,
-    pub(crate) resource_references: Option<Vec<ResourceReference>>,
-    pub(crate) r#type: Type,
-    pub(crate) event: Option<Event>,
-    pub(crate) conditions: Option<Vec<Condition>>,
-    pub(crate) time_activated: Option<DateTime>,
-    pub(crate) inputs: Option<Vec<Input>>,
-    pub(crate) outputs: Option<Vec<Output>>,
-    pub(crate) properties: Option<Properties>,
+pub struct Trigger {
+    pub bom_ref: BomReference,
+    pub uid: String,
+    pub name: Option<String>,
+    pub description: Option<String>,
+    pub resource_references: Option<Vec<ResourceReference>>,
+    pub r#type: Type,
+    pub event: Option<Event>,
+    pub conditions: Option<Vec<Condition>>,
+    pub time_activated: Option<DateTime>,
+    pub inputs: Option<Vec<Input>>,
+    pub outputs: Option<Vec<Output>>,
+    pub properties: Option<Properties>,
 }
 
 impl Validate for Trigger {
@@ -100,14 +100,14 @@ impl Validate for Type {
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub(crate) struct Event {
-    pub(crate) uid: Option<String>,
-    pub(crate) description: Option<String>,
-    pub(crate) time_received: Option<DateTime>,
-    pub(crate) data: Option<Attachment>,
-    pub(crate) source: Option<ResourceReference>,
-    pub(crate) target: Option<ResourceReference>,
-    pub(crate) properties: Option<Properties>,
+pub struct Event {
+    pub uid: Option<String>,
+    pub description: Option<String>,
+    pub time_received: Option<DateTime>,
+    pub data: Option<Attachment>,
+    pub source: Option<ResourceReference>,
+    pub target: Option<ResourceReference>,
+    pub properties: Option<Properties>,
 }
 
 impl Validate for Event {
@@ -130,10 +130,10 @@ impl Validate for Event {
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub(crate) struct Condition {
-    pub(crate) description: Option<String>,
-    pub(crate) expression: Option<String>,
-    pub(crate) properties: Option<Properties>,
+pub struct Condition {
+    pub description: Option<String>,
+    pub expression: Option<String>,
+    pub properties: Option<Properties>,
 }
 
 impl Validate for Condition {
diff --git a/cyclonedx-bom/src/models/formulation/workflow/workspace.rs b/cyclonedx-bom/src/models/formulation/workflow/workspace.rs
index 937a090d..a14e9db1 100644
--- a/cyclonedx-bom/src/models/formulation/workflow/workspace.rs
+++ b/cyclonedx-bom/src/models/formulation/workflow/workspace.rs
@@ -8,18 +8,18 @@ use super::resource_reference::ResourceReference;
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
 pub struct Workspace {
-    pub(crate) bom_ref: BomReference,
-    pub(crate) uid: String,
-    pub(crate) name: Option<String>,
-    pub(crate) aliases: Option<Vec<String>>,
-    pub(crate) description: Option<String>,
-    pub(crate) resource_references: Option<Vec<ResourceReference>>,
-    pub(crate) access_mode: Option<AccessMode>,
-    pub(crate) mount_path: Option<String>,
-    pub(crate) managed_data_type: Option<String>,
-    pub(crate) volume_request: Option<String>,
-    pub(crate) volume: Option<Volume>,
-    pub(crate) properties: Option<Properties>,
+    pub bom_ref: BomReference,
+    pub uid: String,
+    pub name: Option<String>,
+    pub aliases: Option<Vec<String>>,
+    pub description: Option<String>,
+    pub resource_references: Option<Vec<ResourceReference>>,
+    pub access_mode: Option<AccessMode>,
+    pub mount_path: Option<String>,
+    pub managed_data_type: Option<String>,
+    pub volume_request: Option<String>,
+    pub volume: Option<Volume>,
+    pub properties: Option<Properties>,
 }
 
 impl Validate for Workspace {
@@ -53,7 +53,7 @@ pub enum AccessMode {
 }
 
 impl AccessMode {
-    pub(crate) fn new_unchecked<S: AsRef<str>>(s: S) -> Self {
+    pub fn new_unchecked<S: AsRef<str>>(s: S) -> Self {
         match s.as_ref() {
             "read-only" => Self::ReadOnly,
             "read-write" => Self::ReadWrite,
@@ -73,15 +73,15 @@ pub fn validate_access_mode(access_mode: &AccessMode) -> Result<(), ValidationEr
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub(crate) struct Volume {
-    pub(crate) uid: Option<String>,
-    pub(crate) name: Option<String>,
-    pub(crate) mode: Mode,
-    pub(crate) path: Option<String>,
-    pub(crate) size_allocated: Option<String>,
-    pub(crate) persistent: Option<bool>,
-    pub(crate) remote: Option<bool>,
-    pub(crate) properties: Option<Properties>,
+pub struct Volume {
+    pub uid: Option<String>,
+    pub name: Option<String>,
+    pub mode: Mode,
+    pub path: Option<String>,
+    pub size_allocated: Option<String>,
+    pub persistent: Option<bool>,
+    pub remote: Option<bool>,
+    pub properties: Option<Properties>,
 }
 
 impl Validate for Volume {
@@ -104,7 +104,7 @@ pub enum Mode {
 }
 
 impl Mode {
-    pub(crate) fn new_unchecked<S: AsRef<str>>(s: S) -> Self {
+    pub fn new_unchecked<S: AsRef<str>>(s: S) -> Self {
         match s.as_ref() {
             "filesystem" => Self::Filesystem,
             "block" => Self::Block,
diff --git a/cyclonedx-bom/src/models/hash.rs b/cyclonedx-bom/src/models/hash.rs
index b3b24a50..c2b48872 100644
--- a/cyclonedx-bom/src/models/hash.rs
+++ b/cyclonedx-bom/src/models/hash.rs
@@ -87,7 +87,7 @@ pub enum HashAlgorithm {
     UnknownHashAlgorithm(String),
 }
 impl HashAlgorithm {
-    pub(crate) fn new_unchecked<A: AsRef<str>>(value: A) -> Self {
+    pub fn new_unchecked<A: AsRef<str>>(value: A) -> Self {
         match value.as_ref() {
             "MD5" => Self::MD5,
             "SHA-1" => Self::SHA1,
diff --git a/cyclonedx-bom/src/models/lifecycle.rs b/cyclonedx-bom/src/models/lifecycle.rs
index 156267d2..991e15c5 100644
--- a/cyclonedx-bom/src/models/lifecycle.rs
+++ b/cyclonedx-bom/src/models/lifecycle.rs
@@ -57,7 +57,7 @@ impl std::fmt::Display for Phase {
 }
 
 impl Phase {
-    pub(crate) fn new_unchecked<A: AsRef<str>>(value: A) -> Self {
+    pub fn new_unchecked<A: AsRef<str>>(value: A) -> Self {
         match value.as_ref() {
             "design" => Self::Design,
             "pre-build" => Self::PreBuild,
diff --git a/cyclonedx-bom/src/models/modelcard.rs b/cyclonedx-bom/src/models/modelcard.rs
index aacfa339..d2dadebe 100644
--- a/cyclonedx-bom/src/models/modelcard.rs
+++ b/cyclonedx-bom/src/models/modelcard.rs
@@ -120,7 +120,7 @@ pub enum ApproachType {
 }
 
 impl ApproachType {
-    pub(crate) fn new_unchecked<A: AsRef<str>>(value: A) -> Self {
+    pub fn new_unchecked<A: AsRef<str>>(value: A) -> Self {
         match value.as_ref() {
             "supervised" => Self::Supervised,
             "unsupervised" => Self::Unsupervised,
diff --git a/cyclonedx-bom/src/models/service.rs b/cyclonedx-bom/src/models/service.rs
index d0a5b9ba..78628772 100644
--- a/cyclonedx-bom/src/models/service.rs
+++ b/cyclonedx-bom/src/models/service.rs
@@ -218,7 +218,7 @@ pub enum DataFlowType {
 }
 
 impl DataFlowType {
-    pub(crate) fn new_unchecked<A: AsRef<str>>(value: A) -> Self {
+    pub fn new_unchecked<A: AsRef<str>>(value: A) -> Self {
         match value.as_ref() {
             "inbound" => Self::Inbound,
             "outbound" => Self::Outbound,
diff --git a/cyclonedx-bom/src/models/signature.rs b/cyclonedx-bom/src/models/signature.rs
index 43c719c0..1413e2fb 100644
--- a/cyclonedx-bom/src/models/signature.rs
+++ b/cyclonedx-bom/src/models/signature.rs
@@ -131,7 +131,7 @@ pub fn validate_algorithm(algorithm: &Algorithm) -> Result<(), ValidationError>
 
 impl Algorithm {
     #[allow(unused)]
-    pub(crate) fn new_unchecked<A: AsRef<str>>(value: A) -> Self {
+    pub fn new_unchecked<A: AsRef<str>>(value: A) -> Self {
         match value.as_ref() {
             "RS256" => Algorithm::RS256,
             "RS384" => Algorithm::RS384,
diff --git a/cyclonedx-bom/src/models/vulnerability_analysis.rs b/cyclonedx-bom/src/models/vulnerability_analysis.rs
index 64026001..20fe823b 100644
--- a/cyclonedx-bom/src/models/vulnerability_analysis.rs
+++ b/cyclonedx-bom/src/models/vulnerability_analysis.rs
@@ -117,7 +117,7 @@ pub enum ImpactAnalysisState {
 }
 
 impl ImpactAnalysisState {
-    pub(crate) fn new_unchecked<A: AsRef<str>>(value: A) -> Self {
+    pub fn new_unchecked<A: AsRef<str>>(value: A) -> Self {
         match value.as_ref() {
             "resolved" => Self::Resolved,
             "resolved_with_pedigree" => Self::ResolvedWithPedigree,
@@ -163,7 +163,7 @@ pub enum ImpactAnalysisJustification {
 }
 
 impl ImpactAnalysisJustification {
-    pub(crate) fn new_unchecked<A: AsRef<str>>(value: A) -> Self {
+    pub fn new_unchecked<A: AsRef<str>>(value: A) -> Self {
         match value.as_ref() {
             "code_not_present" => Self::CodeNotPresent,
             "code_not_reachable" => Self::CodeNotReachable,
@@ -205,7 +205,7 @@ pub enum ImpactAnalysisResponse {
 }
 
 impl ImpactAnalysisResponse {
-    pub(crate) fn new_unchecked<A: AsRef<str>>(value: A) -> Self {
+    pub fn new_unchecked<A: AsRef<str>>(value: A) -> Self {
         match value.as_ref() {
             "can_not_fix" => Self::CanNotFix,
             "will_not_fix" => Self::WillNotFix,
diff --git a/cyclonedx-bom/src/models/vulnerability_rating.rs b/cyclonedx-bom/src/models/vulnerability_rating.rs
index 5ef73b31..4aba5a86 100644
--- a/cyclonedx-bom/src/models/vulnerability_rating.rs
+++ b/cyclonedx-bom/src/models/vulnerability_rating.rs
@@ -151,7 +151,7 @@ pub enum Severity {
 }
 
 impl Severity {
-    pub(crate) fn new_unchecked<A: AsRef<str>>(value: A) -> Self {
+    pub fn new_unchecked<A: AsRef<str>>(value: A) -> Self {
         match value.as_ref() {
             "critical" => Self::Critical,
             "high" => Self::High,
@@ -165,7 +165,7 @@ impl Severity {
     }
 }
 
-pub(crate) fn validate_score_method(
+pub fn validate_score_method(
     method: &ScoreMethod,
     version: SpecVersion,
 ) -> Result<(), ValidationError> {
@@ -200,7 +200,7 @@ pub enum ScoreMethod {
 }
 
 impl ScoreMethod {
-    pub(crate) fn new_unchecked<A: AsRef<str>>(value: A) -> Self {
+    pub fn new_unchecked<A: AsRef<str>>(value: A) -> Self {
         match value.as_ref() {
             "CVSSv2" => Self::CVSSv2,
             "CVSSv3" => Self::CVSSv3,
diff --git a/cyclonedx-bom/src/models/vulnerability_target.rs b/cyclonedx-bom/src/models/vulnerability_target.rs
index 48690702..72ae024b 100644
--- a/cyclonedx-bom/src/models/vulnerability_target.rs
+++ b/cyclonedx-bom/src/models/vulnerability_target.rs
@@ -168,7 +168,7 @@ pub enum Status {
 }
 
 impl Status {
-    pub(crate) fn new_unchecked<A: AsRef<str>>(value: A) -> Self {
+    pub fn new_unchecked<A: AsRef<str>>(value: A) -> Self {
         match value.as_ref() {
             "affected" => Self::Affected,
             "unaffected" => Self::Unaffected,


Test patch: