Skip to content

Commit 0bbde67

Browse files
committed
fix: Update docs
1 parent eab7a9b commit 0bbde67

2 files changed

Lines changed: 14 additions & 43 deletions

File tree

docs/selective-manifests.md

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -722,7 +722,7 @@ new_builder.sign(source_path, output_path, signer);
722722
723723
An ingredient archive is a serialized `Builder` containing exactly one and only one ingredient (see [Builder archives vs. ingredient archives](#builder-archives-vs-ingredient-archives)). Reading it with `Reader` allows the caller to inspect the ingredient before deciding whether to use it: its thumbnail, whether it carries provenance (e.g. an active manifest), validation status, relationship, etc.
724724
725-
Reading is independent of linking see [Linking an archived ingredient to an action](#linking-an-archived-ingredient-to-an-action) for how to attach the ingredient to an action without reading it first.
725+
Reading is independent of linking, see [Linking an archived ingredient to an action](#linking-an-archived-ingredient-to-an-action) for how to attach the ingredient to an action without reading it first.
726726
727727
```mermaid
728728
flowchart LR
@@ -741,7 +741,7 @@ auto parsed = json::parse(reader.json());
741741
std::string active = parsed["active_manifest"];
742742
auto manifest = parsed["manifests"][active];
743743

744-
// An ingredient archive has exactly one ingredient
744+
// An ingredient archive must always have exactly one ingredient
745745
auto& ingredient = manifest["ingredients"][0];
746746

747747
// Relationship
@@ -785,18 +785,20 @@ if (ingredient.contains("thumbnail")) {
785785
786786
#### Linking an archived ingredient to an action
787787
788-
Linking an archived ingredient to an action is **label-driven**. Set a `label` on the ingredient JSON passed to `add_ingredient` on the signing builder, and use that same string in the action's `ingredientIds`. Reading the archive first is *not* required to link it — `Reader` is only useful when the caller wants to preview the ingredient (thumbnail, provenance, validation status) before deciding whether to use it (see [Reading ingredient details from an ingredient archive](#reading-ingredient-details-from-an-ingredient-archive)).
788+
Linking an **archived** ingredient to an action is **label-driven**: archived ingredients can only be linked to actions using labels.
789789
790-
> [!IMPORTANT]
790+
To do so, set a `label` on the archived ingredient's JSON passed to `add_ingredient` on the builder, and use that same string in the action's `ingredientIds`.
791+
792+
Reading the archive first is *not* required to link it. `Reader` is only useful when the caller wants to preview the ingredient (thumbnail, provenance, validation status) before deciding whether to use it (see [Reading ingredient details from an ingredient archive](#reading-ingredient-details-from-an-ingredient-archive)).
793+
794+
> [!WARNING]
791795
> **`instance_id` does not work as a linking key for ingredient archives.** Use `label` instead.
792796
>
793-
> **Labels baked into the archive ingredient at archive-creation time do not carry through as linking keys.** The label must be re-asserted on the signing builder's `add_ingredient` call.
794-
>
795-
> Both rules apply whether the archive is added by file path or by stream. Attempting to link via `instance_id`, or relying on a baked-in label alone, produces a sign-time error: `Action ingredientId not found: <id>`. See [Troubleshooting linking errors](#troubleshooting-linking-errors).
797+
> **Labels baked into the archive ingredient at archive-creation time do not carry through as linking keys either.** The label must be re-asserted on the signing builder's `add_ingredient` call so action and archived ingredient properly link.
796798
797799
Labels are build-time linking keys only. The SDK may reassign the actual label in the signed manifest.
798800
799-
##### Minimal example
801+
##### Minimal archive to action linking example
800802
801803
Build a manifest whose action references a chosen label, then `add_ingredient` with that label on the signing builder. No `Reader`, no parsing of the archive:
802804
@@ -824,7 +826,7 @@ json manifest_json = {
824826
825827
c2pa::Builder builder(context, manifest_json.dump());
826828
827-
// Same string as in ingredientIds above that is what links the action.
829+
// Same label string as in ingredientIds above: that is what links the action.
828830
builder.add_ingredient(
829831
R"({
830832
"title": "photo.jpg",
@@ -833,12 +835,11 @@ builder.add_ingredient(
833835
})",
834836
archive_path);
835837
838+
// Note that a signing, the SDK may reassign the labels
836839
builder.sign(source_path, output_path, signer);
837840
```
838841

839-
##### Using streams
840-
841-
The `add_ingredient` overload that takes a `std::istream` (with `"application/c2pa"` as the format) follows the same rule — the `label` on the ingredient JSON is what links the action:
842+
The `add_ingredient` overload that takes a `std::istream` (with `"application/c2pa"` as the format) follows the same rules: the `label` on the ingredient JSON is what links the action:
842843

843844
```cpp
844845
std::ifstream archive_file("ingredient_archive.c2pa", std::ios::binary);
@@ -858,7 +859,7 @@ builder.sign(source_path, output_path, signer);
858859
859860
##### Previewing the archive before linking
860861
861-
If you want to inspect the archive (e.g. to decide whether to use it, or to copy `title` from it), open it with `Reader` first, then add it as an ingredient. The Reader step is independent of the linking the link is still established by the `label` on the signing builder's `add_ingredient` call.
862+
If you want to inspect the archive (e.g. to decide whether to use it, or to copy a `title` from it), open it with `Reader` first, then add it as an ingredient. The Reader step is independent of the linking: the link is still established by the `label` on the signing builder's `add_ingredient` call.
862863
863864
```cpp
864865
std::ifstream archive_file("ingredient_archive.c2pa", std::ios::binary);

tests/builder.test.cpp

Lines changed: 0 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -4747,8 +4747,6 @@ TEST_F(BuilderTest, LinkArchiveLabelOnSigningBuilderOpened)
47474747

47484748
TEST_F(BuilderTest, LinkArchiveLabelOnSigningBuilderOpenedFromStream)
47494749
{
4750-
// Same as LinkArchiveLabelOnSigningBuilderOpened but feeds the archive
4751-
// through the std::istream overload of add_ingredient.
47524750
auto archive_path = get_temp_path("label_on_signing_opened_stream.c2pa");
47534751
create_ingredient_archive(archive_path,
47544752
R"({"title": "photo.jpg", "relationship": "parentOf"})");
@@ -4798,9 +4796,6 @@ TEST_F(BuilderTest, LinkArchiveLabelOnSigningBuilderPlacedFromStream)
47984796

47994797
TEST_F(BuilderTest, LinkArchiveInstanceIdOnSigningBuilderFromStreamFails)
48004798
{
4801-
// Stream overload counterpart of LinkArchiveInstanceIdFromArchiveOnSigningBuilder.
4802-
// instance_id cannot be used as a linking key for ingredient archives,
4803-
// regardless of whether the archive is added via path or stream.
48044799
auto context = c2pa::Context();
48054800
auto signer = c2pa_test::create_test_signer();
48064801
auto source_path = c2pa_test::get_fixture_path("A.jpg");
@@ -4850,31 +4845,6 @@ TEST_F(BuilderTest, LinkArchiveInstanceIdOnSigningBuilderFromStreamFails)
48504845
EXPECT_THROW(builder.sign(source_path, output_path, signer), c2pa::C2paException);
48514846
}
48524847

4853-
TEST_F(BuilderTest, LinkArchiveBakedLabelAlsoSetOnSigningBuilder)
4854-
{
4855-
// Probe: same baked label, AND the same label re-asserted on the signing
4856-
// builder's add_ingredient call. Should link successfully (signing-builder
4857-
// label is what counts).
4858-
auto archive_path = get_temp_path("baked_label_also_set.c2pa");
4859-
create_ingredient_archive(archive_path,
4860-
R"({"title": "photo.jpg", "relationship": "parentOf", "label": "baked-label"})");
4861-
4862-
auto manifest_json = make_manifest_with_action("c2pa.opened", "baked-label",
4863-
"http://cv.iptc.org/newscodes/digitalsourcetype/digitalCreation");
4864-
auto context = c2pa::Context();
4865-
auto builder = c2pa::Builder(context, manifest_json.dump());
4866-
4867-
builder.add_ingredient(
4868-
R"({"title": "photo.jpg", "relationship": "parentOf", "label": "baked-label"})",
4869-
archive_path);
4870-
4871-
auto signer = c2pa_test::create_test_signer();
4872-
auto output_path = get_temp_path("baked_label_also_set_result.jpg");
4873-
4874-
bool linked = verify_ingredient_linked(builder, output_path, signer, "c2pa.opened");
4875-
EXPECT_TRUE(linked);
4876-
}
4877-
48784848
TEST_F(BuilderTest, LinkArchiveTwoIngredientsUsingLabels)
48794849
{
48804850
auto archive1 = get_temp_path("two_labels_archive1.c2pa");

0 commit comments

Comments
 (0)