Skip to content
Open
Show file tree
Hide file tree
Changes from 20 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
550319b
feat: add settings structs to public API
ok-nick Sep 24, 2025
2d710cb
feat: add json schemas for settings structs
ok-nick Sep 24, 2025
10aed0e
docs: document all settings structs and fields
ok-nick Sep 25, 2025
992ec27
docs: document settings modules
ok-nick Sep 25, 2025
17927f5
docs: finishing documenting settings structs and fix doc lints
ok-nick Sep 25, 2025
be43767
docs: document main settings struct fields
ok-nick Sep 25, 2025
f752fb5
fix: naming and old field tests
ok-nick Sep 25, 2025
40591e7
fix: add back trust.verify_trust_list
ok-nick Sep 25, 2025
a89476f
fix: doc verify setting warnings, private icon resource, single integ…
ok-nick Sep 29, 2025
b3e6cb4
fix: specify claim generator info operating system as enum
ok-nick Sep 29, 2025
aee4a00
fix: example settings files
ok-nick Sep 29, 2025
2ae744f
docs: clarify `verify_trust` doesn't include `verify_timestamp_trust`
ok-nick Sep 29, 2025
3cfa107
docs: improve certificate status fetch/override docs
ok-nick Sep 29, 2025
3b2cb72
docs: clarify ocsp_fetch and certificate status settings
ok-nick Oct 7, 2025
9fb4585
fix: private `OcspFetchScope`
ok-nick Oct 8, 2025
4efca84
docs: clarify `remote_manifest_fetch` docs
ok-nick Oct 8, 2025
62f34dd
docs: clarify thumbnail settings
ok-nick Oct 8, 2025
7d93444
fix: use LLVM triples as claim generator OS convention
ok-nick Oct 8, 2025
2791e68
Merge branch 'main' into ok-nick/pub-settings
gpeacock Oct 11, 2025
585c9bc
docs: remove hidden attribute for pub(crate) fields and clean up
ok-nick Oct 13, 2025
f3d9ff4
fix: add c2pa-kp-claimSigning OID to trusted EKUs
ok-nick Oct 13, 2025
c2dd7f8
Merge branch 'main' of github.com:contentauth/c2pa-rs into ok-nick/pu…
ok-nick Oct 15, 2025
d5816e6
Merge branch 'main' of github.com:contentauth/c2pa-rs into ok-nick/pu…
ok-nick Oct 16, 2025
2e221f4
fix: don't serde skip builder.actions, only schemars skip
ok-nick Oct 16, 2025
9d80172
fix: feature flag schemars(skip)
ok-nick Oct 16, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 7 additions & 8 deletions cli/tests/fixtures/trust/cawg_sign_settings.toml
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
# c2pa-rs Configuration File

# Version information.
version_major = 1
version_minor = 0
version = 1

# Trust settings for certificate validation.
# [trust]
Expand Down Expand Up @@ -220,13 +219,13 @@ xPd7wFhjRZHfuWb2cs63xjAGjQ==
"""
# String to trust configuration.
trust_config = """
//id-kp-emailProtection
//id-kp-emailProtection
1.3.6.1.5.5.7.3.4
//id-kp-documentSigning
//id-kp-documentSigning
1.3.6.1.5.5.7.3.36
//id-kp-timeStamping
//id-kp-timeStamping
1.3.6.1.5.5.7.3.8
//id-kp-OCSPSigning
//id-kp-OCSPSigning
1.3.6.1.5.5.7.3.9
// MS C2PA Signing
1.3.6.1.4.1.311.76.59.1.9
Expand Down Expand Up @@ -418,8 +417,8 @@ name = "c2pa-rs testing"
version = "1.0.0"
# The operating system the claim generator is running on.
#operating_system.name = "macOS"
# Or if the name isn't specified, it can be inferred automatically.
operating_system.infer = true
# Or specify "auto" to infer the operating system automatically.
Copy link
Collaborator

Choose a reason for hiding this comment

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

Why are we fetching OCSP responses for every certificate as a default!

certificate_status_fetch = "all"
certificate_status_should_override = true

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Hm, that's interesting. @scouten-adobe any input on this?

operating_system = "auto"
# Arbitrary fields can also be defined.
#
# By default, the SDK adds a field "org.cai.c2pa_rs" with the value
Expand Down
8 changes: 3 additions & 5 deletions sdk/examples/c2pa.toml
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
# c2pa-rs Configuration File

# Version information.
version_major = 1
version_minor = 0
version = 1

# # Trust settings for certificate validation.
# [trust]
Expand Down Expand Up @@ -66,9 +65,8 @@ name = "My Service"
# A human readable string of the product's version.
version = "1.0.0"
# The operating system the claim generator is running on.
operating_system.name = "macOS"
# Or if the name isn't specified, it can be inferred automatically.
operating_system.infer = true
# Or specify "auto" to infer the operating system automatically.
operating_system = "macOS"
# Arbitrary fields can also be defined.
#
# By default, the SDK adds a field "org.cai.c2pa_rs" with the value
Expand Down
149 changes: 95 additions & 54 deletions sdk/src/settings/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,10 @@ use crate::{
///
/// These formats are a combination of types supported in [image-rs](https://docs.rs/image/latest/image/enum.ImageFormat.html)
/// and types defined by the [IANA registry media type](https://www.iana.org/assignments/media-types/media-types.xhtml) (as defined in the spec).
#[cfg_attr(feature = "json_schema", derive(schemars::JsonSchema))]
#[derive(Copy, Clone, Debug, Deserialize, PartialEq, Serialize)]
#[serde(rename_all = "lowercase")]
pub(crate) enum ThumbnailFormat {
pub enum ThumbnailFormat {
/// An image in PNG format.
Png,
/// An image in JPEG format.
Expand All @@ -46,9 +47,10 @@ pub(crate) enum ThumbnailFormat {
Tiff,
Copy link
Collaborator

Choose a reason for hiding this comment

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

Why do we support TIFF thumbnails>

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It's naturally supported by the image crate although I have no objection to removing it.

}
/// Quality of the thumbnail.
#[cfg_attr(feature = "json_schema", derive(schemars::JsonSchema))]
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
#[serde(rename_all = "lowercase")]
pub(crate) enum ThumbnailQuality {
pub enum ThumbnailQuality {
/// Low quality.
Low,
/// Medium quality.
Expand All @@ -58,23 +60,36 @@ pub(crate) enum ThumbnailQuality {
}

/// Settings for controlling automatic thumbnail generation.
#[cfg_attr(feature = "json_schema", derive(schemars::JsonSchema))]
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
pub(crate) struct ThumbnailSettings {
pub struct ThumbnailSettings {
/// Whether or not to automatically generate thumbnails.
///
/// The default value is true.
///
/// <div class="warning">
/// This setting is only applicable if the crate is compiled with the `add_thumbnails` feature.
/// </div>
pub enabled: bool,
/// Whether to ignore thumbnail generation errors.
///
/// This may occur, for instance, if the thumbnail media type or color layout isn't
/// supported.
///
/// The default value is true.
pub ignore_errors: bool,
/// The size of the longest edge of the thumbnail.
///
/// This function will resize the input to preserve aspect ratio.
///
/// The default value is 1024.
pub long_edge: u32,
/// Format of the thumbnail.
///
/// If this field isn't specified, the thumbnail format will correspond to the
/// input format.
///
/// The default value is None.
#[serde(skip_serializing_if = "Option::is_none")]
pub format: Option<ThumbnailFormat>,
/// Whether or not to prefer a smaller sized media format for the thumbnail.
Expand All @@ -85,11 +100,15 @@ pub(crate) struct ThumbnailSettings {
///
/// For instance, if the source input type is a PNG, but it doesn't have an alpha channel,
/// the image will be converted to a JPEG of smaller size.
///
/// The default value is true.
pub prefer_smallest_format: bool,
/// The output quality of the thumbnail.
///
/// This setting contains sensible defaults for things like quality, compression, and
/// algorithms for various formats.
///
/// The default value is [`ThumbnailQuality::Medium`].
pub quality: ThumbnailQuality,
}

Expand Down Expand Up @@ -118,55 +137,57 @@ impl SettingsValidate for ThumbnailSettings {
}

/// Settings for the auto actions (e.g. created, opened, placed).
#[allow(unused)]
#[cfg_attr(feature = "json_schema", derive(schemars::JsonSchema))]
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
pub(crate) struct AutoActionSettings {
pub struct AutoActionSettings {
/// Whether to enable this auto action or not.
pub enabled: bool,
/// The default source type for the auto action.
#[serde(skip_serializing_if = "Option::is_none")]
pub source_type: Option<DigitalSourceType>,
}

/// Settings for how to specify the claim generator info's operating system.
#[allow(unused)]
#[cfg_attr(feature = "json_schema", derive(schemars::JsonSchema))]
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
pub(crate) struct ClaimGeneratorInfoOSSettings {
/// Whether or not to infer the operating system.
pub infer: bool,
#[serde(untagged, rename_all = "lowercase")]
pub enum ClaimGeneratorInfoOperatingSystem {
/// Whether or not to automatically infer the operating system.
///
/// This option will attempt to following the [LLVM "triples"] conventions. For more information,
/// see [`ClaimGeneratorInfoOperatingSystem::Other`].
///
/// [LLVM "triples"]: https://clang.llvm.org/docs/CrossCompilation.html#target-triple
Auto,
/// The name of the operating system.
///
/// Note this field overrides [ClaimGeneratorInfoOSSettings::infer].
pub name: Option<String>,
}

impl Default for ClaimGeneratorInfoOSSettings {
fn default() -> Self {
Self {
infer: true,
name: None,
}
}
/// It is recommended to follow the [LLVM "triples"] conventions to define the operating system,
/// with the format `<arch><sub>-<vendor>-<sys>-<env>`. For instance:
/// - `x86_64-unknown-linux-gnu`
/// - `x86_64-pc-windows-msvc`
/// - `arm64-apple-darwin`
///
/// [LLVM "triples"]: https://clang.llvm.org/docs/CrossCompilation.html#target-triple
Other(String),
}

/// Settings for the claim generator info.
#[allow(unused)]
#[cfg_attr(feature = "json_schema", derive(schemars::JsonSchema))]
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
pub(crate) struct ClaimGeneratorInfoSettings {
pub struct ClaimGeneratorInfoSettings {
/// A human readable string naming the claim_generator.
pub name: String,
/// A human readable string of the product's version.
#[serde(skip_serializing_if = "Option::is_none")]
pub version: Option<String>,
/// Reference to an icon.
#[serde(skip_serializing_if = "Option::is_none")]
pub icon: Option<ResourceRef>,
pub(crate) icon: Option<ResourceRef>,
/// Settings for the claim generator info's operating system field.
#[serde(skip_serializing_if = "Option::is_none")]
pub operating_system: Option<ClaimGeneratorInfoOSSettings>,
pub operating_system: Option<ClaimGeneratorInfoOperatingSystem>,
/// Any other values that are not part of the standard.
#[serde(flatten)]
pub other: HashMap<String, toml::Value>,
pub other: HashMap<String, serde_json::Value>,
}

impl TryFrom<ClaimGeneratorInfoSettings> for ClaimGeneratorInfo {
Expand All @@ -178,11 +199,12 @@ impl TryFrom<ClaimGeneratorInfoSettings> for ClaimGeneratorInfo {
version: value.version,
icon: value.icon.map(UriOrResource::ResourceRef),
operating_system: {
let os = value.operating_system.unwrap_or_default();
match os.infer {
true => Some(consts::OS.to_owned()),
false => os.name,
}
value.operating_system.map(|os| match os {
ClaimGeneratorInfoOperatingSystem::Auto => {
format!("{}-unknown-{}", consts::ARCH, consts::OS)
}
ClaimGeneratorInfoOperatingSystem::Other(name) => name,
})
},
other: value
.other
Expand All @@ -198,6 +220,7 @@ impl TryFrom<ClaimGeneratorInfoSettings> for ClaimGeneratorInfo {
}

/// Settings for an action template.
#[cfg_attr(feature = "json_schema", derive(schemars::JsonSchema))]
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
pub(crate) struct ActionTemplateSettings {
/// The label associated with this action. See ([c2pa_action][crate::assertions::actions::c2pa_action]).
Expand All @@ -221,7 +244,7 @@ pub(crate) struct ActionTemplateSettings {
pub description: Option<String>,
/// Additional parameters for the template
#[serde(skip_serializing_if = "Option::is_none")]
pub template_parameters: Option<HashMap<String, toml::Value>>,
pub template_parameters: Option<HashMap<String, serde_json::Value>>,
}

impl TryFrom<ActionTemplateSettings> for ActionTemplate {
Expand Down Expand Up @@ -256,7 +279,6 @@ impl TryFrom<ActionTemplateSettings> for ActionTemplate {
}

/// Settings for an action.
#[allow(unused)]
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
pub(crate) struct ActionSettings {
/// The label associated with this action. See ([`c2pa_action`]).
Expand Down Expand Up @@ -323,34 +345,33 @@ impl TryFrom<ActionSettings> for Action {
///
/// The reason this setting exists only for an [Actions][crate::assertions::Actions] assertion
/// is because of its mandations and reusable fields.
#[allow(unused)]
#[cfg_attr(feature = "json_schema", derive(schemars::JsonSchema))]
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
pub(crate) struct ActionsSettings {
pub struct ActionsSettings {
/// Whether or not to set the [Actions::all_actions_included][crate::assertions::Actions::all_actions_included]
/// field.
#[serde(skip_serializing_if = "Option::is_none")]
pub all_actions_included: Option<bool>,
/// Templates to be added to the [Actions::templates][crate::assertions::Actions::templates] field.
#[serde(skip_serializing_if = "Option::is_none")]
pub templates: Option<Vec<ActionTemplateSettings>>,
// TODO: should we define a new struct for "Action" too, like ActionTemplateSettings?
pub(crate) templates: Option<Vec<ActionTemplateSettings>>,
/// Actions to be added to the [Actions::actions][crate::assertions::Actions::actions] field.
#[serde(skip_serializing_if = "Option::is_none")]
pub actions: Option<Vec<ActionSettings>>,
/// Whether to automatically generate a c2pa.created [Action][crate::assertions::Action]
/// assertion or error that it doesn't already exist.
// TODO: ActionSettings indirectly depends on ActionParameters which contains a serde_cbor::Value and
// schemars can't generate a schema for cbor values. It also doesn't feel right to change our API for
// the sake of json schemas.
#[serde(skip)]
pub(crate) actions: Option<Vec<ActionSettings>>,
/// Whether to automatically generate a c2pa.created [Action] assertion or error that it doesn't already exist.
///
/// For more information about the mandatory conditions for a c2pa.created action assertion, see here:
/// <https://spec.c2pa.org/specifications/specifications/2.2/specs/C2PA_Specification.html#_mandatory_presence_of_at_least_one_actions_assertion>
pub auto_created_action: AutoActionSettings,
/// Whether to automatically generate a c2pa.opened [Action][crate::assertions::Action]
/// assertion or error that it doesn't already exist.
/// Whether to automatically generate a c2pa.opened [Action] assertion or error that it doesn't already exist.
///
/// For more information about the mandatory conditions for a c2pa.opened action assertion, see here:
/// <https://spec.c2pa.org/specifications/specifications/2.2/specs/C2PA_Specification.html#_mandatory_presence_of_at_least_one_actions_assertion>
pub auto_opened_action: AutoActionSettings,
/// Whether to automatically generate a c2pa.placed [Action][crate::assertions::Action]
/// assertion or error that it doesn't already exist.
/// Whether to automatically generate a c2pa.placed [Action] assertion or error that it doesn't already exist.
///
/// For more information about the mandatory conditions for a c2pa.placed action assertion, see:
/// <https://spec.c2pa.org/specifications/specifications/2.2/specs/C2PA_Specification.html#_relationship>
Expand Down Expand Up @@ -390,9 +411,9 @@ impl SettingsValidate for ActionsSettings {

// TODO: do more validation on URL fields, cert fields, etc.
/// Settings for the [Builder][crate::Builder].
#[allow(unused)]
#[cfg_attr(feature = "json_schema", derive(schemars::JsonSchema))]
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize, Default)]
pub(crate) struct BuilderSettings {
pub struct BuilderSettings {
/// Claim generator info that is automatically added to the builder.
///
/// Note that this information will prepend any claim generator info
Expand All @@ -405,18 +426,38 @@ pub(crate) struct BuilderSettings {
///
/// For more information on the reasoning behind this field see [ActionsSettings].
pub actions: ActionsSettings,

// Certificate statuses will be fetched for either all the manifest labels, or just the active manifest.
pub certificate_status_fetch: Option<OcspFetch>,

// Whether or not existing OCSP responses should be overridden by new values.
pub certificate_status_should_override: Option<bool>,
// TODO: this setting affects fetching and generation of the assertion; needs clarification
/// Whether to create [`CertificateStatus`] assertions for manifests to store certificate revocation
/// status. The assertion can be fetched for the active manifest or for all manifests (including
/// ingredients).
///
/// The default is to not fetch them at all.
///
/// See more information in the spec here:
/// <https://spec.c2pa.org/specifications/specifications/2.2/specs/C2PA_Specification.html#certificate_status_assertion>
///
/// [`CertificateStatus`]: crate::assertions::CertificateStatus
pub(crate) certificate_status_fetch: Option<OcspFetchScope>,
// TODO: this setting affects fetching and generation of the assertion; needs clarification
/// Whether to only use [`CertificateStatus`] assertions to check certificate revocation status. If there
/// is a stapled OCSP in the COSE claim of the manifest, it will be ignored. If [`Verify::ocsp_fetch`] is
/// enabled, it will also be ignored.
///
/// The default value is false.
///
/// [`CertificateStatus`]: crate::assertions::CertificateStatus
/// [`Verify::ocsp_fetch`]: crate::settings::Verify::ocsp_fetch
pub(crate) certificate_status_should_override: Option<bool>,
}

/// The scope of which manifests to fetch for OCSP.
#[cfg_attr(feature = "json_schema", derive(schemars::JsonSchema))]
#[derive(Copy, Clone, Debug, Deserialize, PartialEq, Serialize)]
#[serde(rename_all = "lowercase")]
pub(crate) enum OcspFetch {
pub(crate) enum OcspFetchScope {
/// Fetch OCSP for all manifests.
All,
/// Fetch OCSP for the active manifest only.
Active,
Copy link
Collaborator

Choose a reason for hiding this comment

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

How is this meant to be used in the settings file? Without an "off" choice then the presence of OCSPFetchScope will mean we are fetching responses. I do not thing fetching should ever default to on.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

certificate_status_fetch is defined as Option<OcspFetchScope> that defaults to None.

}

Expand Down
Loading
Loading