You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/selective-manifests.md
+162-2Lines changed: 162 additions & 2 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -559,7 +559,9 @@ with Reader("application/c2pa", archive_stream, context=ctx) as reader:
559
559
560
560
### Identifying ingredients in archives
561
561
562
-
When building an ingredient archive, you can set `instance_id` on the ingredient to give it a stable, caller-controlled identifier. This field survives archiving and signing unchanged. The `description` and `informational_URI` fields also survive and can carry additional metadata about the ingredient's origin.
562
+
When building an ingredient archive, you can set `instance_id` on the ingredient to give it a stable, caller-controlled identifier. This field survives archiving and signing unchanged, so it can be used to look up a specific ingredient from a catalog archive. The `description` and `informational_URI` fields also survive and can carry additional metadata about the ingredient's origin.
563
+
564
+
`instance_id` is only for identification and catalog lookups. It cannot be used as a linking key in `ingredientIds` when linking ingredient archives to actions — use `label` for that (see [Linking an archived ingredient to an action](#linking-an-archived-ingredient-to-an-action)).
563
565
564
566
```py
565
567
# Set instance_id when adding the ingredient to the archive builder
@@ -768,6 +770,121 @@ with Reader("application/c2pa", archive_stream, context=ctx) as reader:
768
770
new_builder.sign("image/jpeg", source, dest)
769
771
```
770
772
773
+
### Reading ingredient details from an ingredient archive
774
+
775
+
An ingredient archive is a serialized `Builder` containing exactly 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.
After reading the ingredient details from an ingredient archive, the ingredient can be added to a new `Builder` and linked to an action. You must assign a `label` in the `add_ingredient()` call on the signing builder and use that label as the linking key in `ingredientIds`. Labels baked into the archive ingredient are not carried through, and `instance_id` does not work as a linking key for ingredient archives.
831
+
832
+
Labels are only used as build-time linking keys. The SDK may reassign the actual label in the signed manifest.
833
+
834
+
Assign a `label` in the `add_ingredient()` call and reference that same label in `ingredientIds`. This works whether or not the ingredient has an `instance_id`.
with Builder(manifest_json, context=ctx) as builder:
870
+
# The label on the ingredient matches the entry in ingredientIds
871
+
archive_file.seek(0)
872
+
builder.add_ingredient(
873
+
{
874
+
"title": ingredient["title"],
875
+
"relationship": "parentOf",
876
+
"label": "archived-ingredient",
877
+
},
878
+
"application/c2pa",
879
+
archive_file,
880
+
)
881
+
882
+
withopen("source.jpg", "rb") as source, open("output.jpg", "w+b") as dest:
883
+
builder.sign("image/jpeg", source, dest)
884
+
885
+
reader.close()
886
+
```
887
+
771
888
### Merging multiple working stores
772
889
773
890
> [!NOTE]
@@ -839,3 +956,46 @@ with Builder({
839
956
# configure a dedicated Signer explicitly.
840
957
builder.sign("image/jpeg", source, dest)
841
958
```
959
+
960
+
## Controlling manifest embedding
961
+
962
+
By default, `sign()` embeds the manifest directly inside the output asset file.
963
+
964
+
### Remove the manifest from the asset entirely
965
+
966
+
Use `set_no_embed()` so the signed asset contains no embedded manifest. The manifest bytes are returned from `sign()` and can be stored separately (as a sidecar file, on a server, etc.):
967
+
968
+
```mermaid
969
+
flowchart LR
970
+
subgraph Default["Default (embedded)"]
971
+
A1[Output Asset] --- A2[Image data + C2PA manifest]
972
+
end
973
+
974
+
subgraph NoEmbed["With set_no_embed()"]
975
+
B1[Output Asset] ~~~ B2[Manifest bytes with store as sidecar or uploaded to server]
0 commit comments