Skip to content

Commit d4282ec

Browse files
author
Tania Mathern
committed
fix: Docs
1 parent fca1a96 commit d4282ec

2 files changed

Lines changed: 20 additions & 32 deletions

File tree

docs/selective-manifests.md

Lines changed: 18 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -564,7 +564,7 @@ When building an ingredient archive, you can set `instance_id` on the ingredient
564564
`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)).
565565

566566
```py
567-
# Set instance_id when adding the ingredient to the archive builder
567+
# Set instance_id when adding the ingredient to the archive builder.
568568
builder = Builder.from_json(manifest_json)
569569
with open("photo-A.jpg", "rb") as f:
570570
builder.add_ingredient(
@@ -778,40 +778,38 @@ An ingredient archive is a serialized `Builder` containing exactly one ingredien
778778
flowchart LR
779779
IA["ingredient_archive.c2pa"] -->|"Reader(application/c2pa)"| JSON["JSON + resources"]
780780
JSON --> TH["Thumbnail"]
781-
JSON --> AM["Active manifest?"]
781+
JSON --> AM["Active manifest (only if ingredient has Content Credentials)"]
782782
JSON --> VS["Validation status"]
783783
JSON --> REL["Relationship"]
784784
```
785785

786786
```py
787-
# Open the ingredient archive
787+
# Open the ingredient archive.
788788
with open("ingredient_archive.c2pa", "rb") as archive_file:
789789
reader = Reader("application/c2pa", archive_file, context=ctx)
790790
parsed = json.loads(reader.json())
791791
active = parsed["active_manifest"]
792792
manifest = parsed["manifests"][active]
793793

794-
# An ingredient archive has exactly one ingredient
794+
# An ingredient archive has exactly one ingredient.
795795
ingredient = manifest["ingredients"][0]
796796

797-
# Relationship
798-
relationship = ingredient["relationship"] # e.g. "parentOf", "componentOf", "inputTo"
797+
# Relationship e.g. "parentOf", "componentOf", "inputTo".
798+
relationship = ingredient["relationship"]
799799

800-
# Instance ID (optional, set by the caller via add_ingredient or derived from XMP metadata)
800+
# Instance ID (optional, can be set by caller).
801801
instance_id = ingredient.get("instance_id")
802802

803803
# Active manifest:
804-
# When present, the ingredient was a signed asset and its manifest label
805-
# points into the top-level "manifests" dictionary.
804+
# When present, the ingredient had content credentials itself.
806805
if "active_manifest" in ingredient:
807806
ing_manifest_label = ingredient["active_manifest"]
808807
ing_manifest = parsed["manifests"][ing_manifest_label]
809808
# ing_manifest contains the ingredient's own assertions, actions, etc.
810809

811810
# Validation status.
812811
# The top-level "validation_status" array covers the entire manifest store,
813-
# including this ingredient's manifest. An empty or absent array means
814-
# no validation errors were found.
812+
# including this ingredient's manifest.
815813
if "validation_status" in parsed:
816814
for status in parsed["validation_status"]:
817815
print(f"{status['code']}: {status['explanation']}")
@@ -831,22 +829,23 @@ After reading the ingredient details from an ingredient archive, the ingredient
831829

832830
Labels are only used as build-time linking keys. The SDK may reassign the actual label in the signed manifest.
833831

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`.
832+
Assign a `label` in the `add_ingredient()` call and reference that same label in `ingredientIds` to link an ingredient to an action.
835833

836834
```py
837835
ctx = Context.from_dict({
838836
"builder": {"claim_generator_info": {"name": "an-application", "version": "0.1.0"}},
839837
"signer": signer,
840838
})
841839

842-
# Read the ingredient archive
840+
# Read the ingredient archive.
843841
with open("ingredient_archive.c2pa", "rb") as archive_file:
844842
reader = Reader("application/c2pa", archive_file, context=ctx)
845843
parsed = json.loads(reader.json())
846844
active = parsed["active_manifest"]
847845
ingredient = parsed["manifests"][active]["ingredients"][0]
848846

849-
# Use a caller-assigned label as the linking key
847+
# Use a label as the linking key.
848+
# Any label can be used, as long as it uniquely identifies the link.
850849
manifest_json = {
851850
"claim_generator_info": [{"name": "an-application", "version": "0.1.0"}],
852851
"assertions": [
@@ -867,7 +866,7 @@ with open("ingredient_archive.c2pa", "rb") as archive_file:
867866
}
868867

869868
with Builder(manifest_json, context=ctx) as builder:
870-
# The label on the ingredient matches the entry in ingredientIds
869+
# The label on the ingredient must match the entry in ingredientIds on the action.
871870
archive_file.seek(0)
872871
builder.add_ingredient(
873872
{
@@ -963,18 +962,7 @@ By default, `sign()` embeds the manifest directly inside the output asset file.
963962

964963
### Remove the manifest from the asset entirely
965964

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]
976-
end
977-
```
965+
Use `set_no_embed()` so the signed asset contains no embedded manifest store. The manifest store bytes are returned from `sign()` and can be stored separately (e.g. as a sidecar file).
978966

979967
```py
980968
ctx = Context.from_dict({
@@ -987,9 +975,9 @@ builder.set_remote_url("<<URI/URL to remote storage of manifest bytes>>")
987975

988976
with open("source.jpg", "rb") as source, open("output.jpg", "w+b") as dest:
989977
manifest_bytes = builder.sign("image/jpeg", source, dest)
990-
# manifest_bytes contains the full manifest store
991-
# Upload manifest_bytes to the remote URL
992-
# The output asset has no embedded manifest
978+
# manifest_bytes contains the full manifest store.
979+
# Upload manifest_bytes to the remote URL.
980+
# The output asset has no embedded manifest.
993981
```
994982

995983
Reading back:

docs/working-stores.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -442,7 +442,7 @@ To link an ingredient archive to an action via `ingredientIds`, you must use a `
442442
```py
443443
import io, json
444444

445-
# Step 1: Create the ingredient archive
445+
# Step 1: Create the ingredient archive.
446446
archive_builder = Builder.from_json({
447447
"claim_generator_info": [{"name": "my-app", "version": "1.0"}],
448448
"assertions": [],
@@ -457,7 +457,7 @@ archive = io.BytesIO()
457457
archive_builder.to_archive(archive)
458458
archive.seek(0)
459459

460-
# Step 2: Build a manifest with an action that references the ingredient
460+
# Step 2: Build a manifest with an action that references the ingredient.
461461
manifest_json = {
462462
"claim_generator_info": [{"name": "my-app", "version": "1.0"}],
463463
"assertions": [

0 commit comments

Comments
 (0)