PageSourceSearch

https://opensource.contentauthenticity.org/assets/js/d8d52ac0.9c611f1c.js

js contentauthenticity.org collected 2026-09-24 08:25:01 UTC 31,889 bytes, 1 lines download raw bytes

1"use strict";(globalThis.webpackChunkopensource_contentauth_org=globalThis.webpackChunkopensource_contentauth_org||[]).push([[2292],{3201:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>c,contentTitle:()=>a,default:()=>h,frontMatter:()=>r,metadata:()=>i,toc:()=>l});const i=JSON.parse('{"id":"sdk-repos/c2pa-python/docs/intents","title":"Using Builder intents","description":"Intents enable validation, add the actions required by the C2PA specification, and help prevent invalid operations when using a Builder. Intents are about the operation (create, edit, update) executed on the source asset.","source":"@site/docs/sdk-repos/c2pa-python/docs/intents.md","sourceDirName":"sdk-repos/c2pa-python/docs","slug":"/sdk-repos/c2pa-python/docs/intents","permalink":"/docs/sdk-repos/c2pa-python/docs/intents","draft":false,"unlisted":false,"editUrl":"https://github.com/contentauth/c2pa-python/edit/main/docs/intents.md","tags":[],"version":"current","frontMatter":{},"sidebar":"docs","previous":{"title":"Configuring SDK settings","permalink":"/docs/sdk-repos/c2pa-python/docs/context-settings"},"next":{"title":"Manifests, working stores, and archives","permalink":"/docs/sdk-repos/c2pa-python/docs/working-stores"}}');var d=t(4848),s=t(8453);const r={},a="Using Builder intents",c={},l=[{value:"Why use intents?",id:"why-use-intents",level:2},{value:"Setting the intent",id:"setting-the-intent",level:2},{value:"Using Context",id:"using-context",level:3},{value:"Using set_intent on the Builder",id:"using-set_intent-on-the-builder",level:3},{value:"Intent precedence",id:"intent-precedence",level:3},{value:"How intents relate to the source stream",id:"how-intents-relate-to-the-source-stream",level:2},{value:"How intent relates to add_ingredient",id:"how-intent-relates-to-add_ingredient",level:3},{value:"Importing the enums",id:"importing-the-enums",level:2},{value:"Using set_intent",id:"using-set_intent",level:3},{value:"Intent types",id:"intent-types",level:3},{value:"C2paDigitalSourceType",id:"c2padigitalsourcetype",level:3},{value:"Choosing the right intent",id:"choosing-the-right-intent",level:2},{value:"Create intent",id:"create-intent",level:2},{value:"Example: New digital creation",id:"example-new-digital-creation",level:3},{value:"Example: Marking AI-generated content",id:"example-marking-ai-generated-content",level:3},{value:"Example: Create with additional manifest metadata",id:"example-create-with-additional-manifest-metadata",level:3},{value:"Edit intent",id:"edit-intent",level:2},{value:"Example: Editing an asset",id:"example-editing-an-asset",level:3},{value:"Example: Editing with a manually-added parent",id:"example-editing-with-a-manually-added-parent",level:3},{value:"Example: Editing with additional component ingredients",id:"example-editing-with-additional-component-ingredients",level:3},{value:"Update intent",id:"update-intent",level:2},{value:"Example: Adding metadata to a signed asset",id:"example-adding-metadata-to-a-signed-asset",level:3}];function o(e){const n={a:"a",code:"code",em:"em",h1:"h1",h2:"h2",h3:"h3",header:"header",li:"li",mermaid:"mermaid",ol:"ol",p:"p",pre:"pre",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",ul:"ul",...(0,s.R)(),...e.components};return(0,d.jsxs)(d.Fragment,{children:[(0,d.jsx)(n.header,{children:(0,d.jsx)(n.h1,{id:"using-builder-intents",children:"Using Builder intents"})}),"\n",(0,d.jsxs)(n.p,{children:[(0,d.jsx)(n.em,{children:"Intents"})," enable validation, add the actions required by the C2PA specification, and help prevent invalid operations when using a ",(0,d.jsx)(n.code,{children:"Builder"}),". Intents are about the operation (create, edit, update) executed on the source asset."]}),"\n",(0,d.jsx)(n.h2,{id:"why-use-intents",children:"Why use intents?"}),"\n",(0,d.jsxs)(n.p,{children:["Without intents, you have to manually construct the correct manifest structure: adding the required actions (",(0,d.jsx)(n.code,{children:"c2pa.created"})," or ",(0,d.jsx)(n.code,{children:"c2pa.opened"})," as the first action per the specification), setting digital source types, managing ingredients, and linking actions to ingredients. Getting any of this wrong produces a non-compliant manifest."]}),"\n",(0,d.jsxs)(n.p,{children:["With intents, the caller declares ",(0,d.jsx)(n.em,{children:"what is being done"})," and ",(0,d.jsx)(n.code,{children:"Builder"})," handles the rest."]}),"\n",(0,d.jsxs)(n.p,{children:["For example, without intents you have to manually wire up actions and make sure ingredients are properly linked to actions. This is especially important for ",(0,d.jsx)(n.code,{children:"parentOf"})," ingredient relationships with the ",(0,d.jsx)(n.code,{children:"c2pa.opened"})," action."]}),"\n",(0,d.jsx)(n.pre,{children:(0,d.jsx)(n.code,{className:"language-py",children:'with Builder({\n    "assertions": [\n        {\n            "label": "c2pa.actions",\n            "data": {\n                "actions": [\n                    {\n                        "action": "c2pa.created",\n                        "digitalSourceType": "http://cv.iptc.org/newscodes/
1digitalsourcetype/trainedAlgorithmicMedia",\n                    }\n                ]\n            },\n        }\n    ],\n}) as builder:\n    with open("source.jpg", "rb") as source, open("output.jpg", "wb") as dest:\n        builder.sign(signer, "image/jpeg", source, dest)\n'})}),"\n",(0,d.jsxs)(n.p,{children:["But with intents, ",(0,d.jsx)(n.code,{children:"Builder"})," generates the actions automatically; for example:"]}),"\n",(0,d.jsx)(n.pre,{children:(0,d.jsx)(n.code,{className:"language-py",children:'with Builder({}) as builder:\n    builder.set_intent(\n        C2paBuilderIntent.CREATE,\n        C2paDigitalSourceType.TRAINED_ALGORITHMIC_MEDIA,\n    )\n    with open("source.jpg", "rb") as source, open("output.jpg", "wb") as dest:\n        builder.sign(signer, "image/jpeg", source, dest)\n'})}),"\n",(0,d.jsxs)(n.p,{children:["Both of these code snippets produce the same signed manifest. But with intents, ",(0,d.jsx)(n.code,{children:"Builder"})," validates the setup and fills in the required structure."]}),"\n",(0,d.jsx)(n.h2,{id:"setting-the-intent",children:"Setting the intent"}),"\n",(0,d.jsxs)(n.p,{children:["You can set the intent on a ",(0,d.jsx)(n.code,{children:"Builder"})," instance by:"]}),"\n",(0,d.jsxs)(n.ul,{children:["\n",(0,d.jsx)(n.li,{children:(0,d.jsx)(n.a,{href:"#using-context",children:"Using Context"})}),"\n",(0,d.jsx)(n.li,{children:(0,d.jsxs)(n.a,{href:"#using-set_intent-on-the-builder",children:["Using ",(0,d.jsx)(n.code,{children:"set_intent"})," on the ",(0,d.jsx)(n.code,{children:"Builder"})]})}),"\n"]}),"\n",(0,d.jsxs)(n.p,{children:["Don't set the intent using the deprecated ",(0,d.jsx)(n.code,{children:"load_settings()"})," function. For existing code, see ",(0,d.jsx)(n.a,{href:"/docs/sdk-repos/c2pa-python/docs/context-settings#migrating-from-load_settings",children:"Context and settings - Migrating from load_settings"}),"."]}),"\n",(0,d.jsx)(n.h3,{id:"using-context",children:"Using Context"}),"\n",(0,d.jsxs)(n.p,{children:["Pass the intent through a ",(0,d.jsx)(n.code,{children:"Context"})," object when creating a ",(0,d.jsx)(n.code,{children:"Builder"}),". This keeps intent configuration alongside other builder settings such as ",(0,d.jsx)(n.code,{children:"claim_generator_info"})," and ",(0,d.jsx)(n.code,{children:"thumbnail"}),"."]}),"\n",(0,d.jsx)(n.pre,{children:(0,d.jsx)(n.code,{className:"language-py",children:'from c2pa import Context, Builder\n\nctx = Context.from_dict({\n    "builder": {\n        "intent": {"Create": "digitalCapture"},\n        "claim_generator_info": {"name": "My App", "version": "0.1.0"},\n    }\n})\n\nwith Builder({}, context=ctx) as builder:\n    with open("source.jpg", "rb") as source, open("output.jpg", "wb") as dest:\n        builder.sign(signer, "image/jpeg", source, dest)\n'})}),"\n",(0,d.jsxs)(n.p,{children:["You can reuse the same ",(0,d.jsx)(n.code,{children:"Context"})," across multiple ",(0,d.jsx)(n.code,{children:"Builder"})," instances, ensuring consistent configuration:"]}),"\n",(0,d.jsx)(n.pre,{children:(0,d.jsx)(n.code,{className:"language-py",children:'ctx = Context.from_dict({\n    "builder": {\n        "intent": "edit",\n        "claim_generator_info": {"name": "Batch Editor"},\n    }\n})\n\nfor path in image_paths:\n    with Builder({}, context=ctx) as builder:\n        builder.sign_file(path, output_path(path), signer)\n'})}),"\n",(0,d.jsx)(n.h3,{id:"using-set_intent-on-the-builder",children:"Using set_intent on the Builder"}),"\n",(0,d.jsxs)(n.p,{children:["Call ",(0,d.jsx)(n.code,{children:"set_intent"})," directly on a ",(0,d.jsx)(n.code,{children:"Builder"})," instance for one-off operations or when the intent is determined at runtime. For example:"]}),"\n",(0,d.jsx)(n.pre,{children:(0,d.jsx)(n.code,{className:"language-py",children:'with Builder({}) as builder:\n    builder.set_intent(\n        C2paBuilderIntent.CREATE,\n        C2paDigitalSourceType.TRAINED_ALGORITHMIC_MEDIA,\n    )\n    with open("source.jpg", "rb") as source, open("output.jpg", "wb") as dest:\n        builder.sign(signer, "image/jpeg", source, dest)\n'})}),"\n",(0,d.jsx)(n.h3,{id:"intent-precedence",children:"Intent precedence"}),"\n",(0,d.jsxs)(n.p,{children:["When an intent is configured in multiple places, the most specific setting takes precedence.\nIf ",(0,d.jsx)(n.code,{children:"set_intent"})," is called on a ",(0,d.jsx)(n.code,{children:"Builder"})," instance, it takes precedence over all other sources."]}),"\n",(0,d.jsx)(n.mermaid,{value:'flowchart TD\n    Check{Was set_intent called\n    on the Builder?}\n    Check --\x3e |Yes| UseSetIntent["Use set_intent value"]\n    Check --\x3e |No| CheckCtx{Was a Context with\n    builder.intent provided?}
1\n    CheckCtx --\x3e |Yes| UseCtx["Use Context intent"]\n    CheckCtx --\x3e |No| CheckGlobal{Was load_settings called\n    with builder.intent?}\n    CheckGlobal --\x3e |Yes| UseGlobal["Use global intent\n    (deprecated)"]\n    CheckGlobal --\x3e |No| NoIntent["No intent set.\n    Caller must define actions\n    manually in manifest JSON."]'}),"\n",(0,d.jsx)(n.h2,{id:"how-intents-relate-to-the-source-stream",children:"How intents relate to the source stream"}),"\n",(0,d.jsxs)(n.p,{children:["The intent operates on the source passed to ",(0,d.jsx)(n.code,{children:"sign()"}),", not on any ingredient added via ",(0,d.jsx)(n.code,{children:"add_ingredient()"}),"."]}),"\n",(0,d.jsx)(n.p,{children:"The following diagram shows what happens at sign time for each intent:"}),"\n",(0,d.jsx)(n.mermaid,{value:'flowchart LR\n    subgraph CREATE\n        S1[source stream] --\x3e B1[Builder]\n        B1 --\x3e O1[signed output]\n        B1 -. adds .-> A1["c2pa.created action\n        + digital source type"]\n    end'}),"\n",(0,d.jsx)(n.mermaid,{value:'flowchart LR\n    subgraph EDIT\n        S2[source stream] --\x3e B2[Builder]\n        B2 --\x3e O2[signed output]\n        S2 -. auto-created as .-> P2[parentOf ingredient]\n        P2 --\x3e B2\n        B2 -. adds .-> A2["c2pa.opened action\n        linked to parent"]\n    end'}),"\n",(0,d.jsx)(n.mermaid,{value:'flowchart LR\n    subgraph UPDATE\n        S3[source stream] --\x3e B3[Builder]\n        B3 --\x3e O3[signed output]\n        S3 -. auto-created as .-> P3[parentOf ingredient]\n        P3 --\x3e B3\n        B3 -. adds .-> A3["c2pa.opened action\n        linked to parent"]\n        B3 -. restricts .-> R3[content must not change]\n    end'}),"\n",(0,d.jsxs)(n.p,{children:["For ",(0,d.jsx)(n.code,{children:"Edit"})," and ",(0,d.jsx)(n.code,{children:"Update"})," intents, ",(0,d.jsx)(n.code,{children:"Builder"})," looks at the source stream, and if no ",(0,d.jsx)(n.code,{children:"parentOf"})," ingredient has been added manually, it automatically creates one from that stream (and adds the needed action). The source stream ",(0,d.jsx)(n.em,{children:"becomes"})," the parent ingredient. If a ",(0,d.jsx)(n.code,{children:"parentOf"})," ingredient has already been added manually (via ",(0,d.jsx)(n.code,{children:"add_ingredient"}),"), ",(0,d.jsx)(n.code,{children:"Builder"})," uses that one instead and does not automatically create one from the source."]}),"\n",(0,d.jsx)(n.h3,{id:"how-intent-relates-to-add_ingredient",children:"How intent relates to add_ingredient"}),"\n",(0,d.jsxs)(n.p,{children:["The ",(0,d.jsx)(n.code,{children:"Builder"})," intent controls what the ",(0,d.jsx)(n.code,{children:"Builder"})," does with the source stream (source asset) at sign time. The ",(0,d.jsx)(n.code,{children:"add_ingredient"})," method adds other ingredients explicitly. These are separate concerns."]}),"\n",(0,d.jsx)(n.mermaid,{value:'flowchart TD\n    Intent["Intent\n    (via Context, set_intent,\n    or load_settings)"] --\x3e Q{Intent type?}\n    Q --\x3e |CREATE| CreateFlow["No parent allowed\n    Source stream is new content"]\n    Q --\x3e |EDIT or UPDATE| EditFlow{Was a parentOf ingredient\n    added via add_ingredient?}\n    EditFlow --\x3e |No| Auto["Builder auto-creates\n    parentOf from source stream"]\n    EditFlow --\x3e |Yes| Manual["Builder uses the\n    manually-added parent"]\n    Auto --\x3e Opened["Builder adds c2pa.opened\n    action linked to parent"]\n    Manual --\x3e Opened\n    CreateFlow --\x3e Created["Builder adds c2pa.created\n    action + digital source type"]\n\n    AddIngredient["add_ingredient()"] --\x3e IngType{relationship?}\n    IngType --\x3e |parentOf| ParentIng["Overrides auto-parent\n    for EDIT/UPDATE"]\n    IngType --\x3e |componentOf| CompIng["Additional ingredient\n    not affected by intent"]\n    ParentIng --\x3e EditFlow'}),"\n",(0,d.jsx)(n.h2,{id:"importing-the-enums",children:"Importing the enums"}),"\n",(0,d.jsxs)(n.p,{children:["The ",(0,d.jsx)(n.code,{children:"C2paBuilderIntent"})," and ",(0,d.jsx)(n.code,{children:"C2paDigitalSourceType"})," enums are available from the ",(0,d.jsx)(n.code,{children:"c2pa"})," package:"]}),"\n",(0,d.jsx)(n.pre,{children:(0,d.jsx)(n.code,{className:"language-py",children:"from c2pa import (\n    C2paBuilderIntent,\n    C2paDigitalSourceType,\n)\n"})}),"\n",(0,d.jsx)(n.h3,{id:"using-set_intent",children:"Using set_intent"}),"\n",(0,d.jsxs)(n.p,{children:["Use the ",(0,d.jsx)(n.code,{children:"Builder.set_intent"})," method to specify the intent:"]}),"\n",(0,d.jsx)(n.pre,{children:(0,d.jsx)(n.code,{className:"language-py",children:"builder.set_intent(intent, digital_source_type=C2paDigitalSourceType.EMPTY)\n"})}),"\n",(0,d.jsx)(n.p,{children:"Where:"}),"\n",(0,d.jsxs)(n.ul,{children:["\n",(0,d.jsxs)(n.li,{children:[(0,d.jsx)(n.code,{children:"intent"})," is one of the ",(0,d.jsx)(n.a,{href:"#intent-types",children:"intent types"}),"."]}),"\n",(0,d.jsxs)(n.li,{children:[(0,d.jsx)(n.code,{children:"digital_source_type"})," is one of the ",(0,d.jsxs)(n.a,{href:"#c2padigitalsourcetype",children:[(0,d.jsx)(n.code,{children:"C2paDigitalSourceType"})," values"]})," that describes how the asset was made. Required for the ",(0,d.jsx)(n.code,{children:"Create"})," intent. Defaults to ",(0,d.jsx)(n.code,{children:"EMPTY"}),"."]}),"\n"]}),"\n",(0,d.jsxs)(n.p,{children:["Raises ",(0,d.jsx)(n.code,{children:"C2paError"})," if the intent cannot be set (for example, if a ",(0,d.jsx)(n.code,{children:"parentOf"})," ingredient exists with ",(0,d.jsx)(n.code,{children:"Create"}),")."]}),"\n",(0,d.jsx)(n.h3,{id:"intent-types",children:"Intent types"}),"\n",(0,d.jsxs)(n.p,{children:["Intent types can be any ",(0,d.jsx)(n.code,{children:"C2paBuilderIntent"})," value:"]}),"\n",(0,d.jsxs)(n.table,{children:[(0,d.jsx)(n.thead,{children:(0,d.jsxs)(n.tr,{children:[(0,d.jsx)(n.th,{children:"Intent"}),(0,d.jsx)(n.th,{children:"Operation"}),(0,d.jsx)(n.th,{children:"Parent ingredient"}),(0,d.jsx)(n.th,{children:"Auto-generated action"})]})}),(0,d.jsxs)(n.tbody,{children:[(0,d.jsxs)(n.tr,{children:[(0,d.jsx)(n.td,{children:(0,d.jsx)(n.code,{children:"CREATE"})}),(0,d.jsx)(n.td,{children:"Brand-new content"}),(0,d.jsx)(n.td,{children:"Must NOT have one"}),(0,d.jsx)(n.td,{children:(0,d.jsx)(n.code,{children:"c2pa.created"})})]}),(0,d.jsxs)(n.tr,{children:[(0,d.jsx)(n.td,{children:(0,d.jsx)(n.code,{children:"EDIT"})}),(0,d.jsx)(n.td,{children:"Modifying existing content"}),(0,d.jsx)(n.td,{children:"Auto-created from the source stream if not provided"}),(0,d.jsxs)(n.td,{children:[(0,d.jsx)(n.code,{children:"c2pa.opened"})," (linked to parent)"]})]}),(0,d.jsxs)(n.tr,{children:[(0,d.jsx)(n.td,{children:(0,d.jsx)(n.code,{children:"UPDATE"})}),(0,d.jsx)(n.td,{children:"Metadata-only changes"}),(0,d.jsx)(n.td,{children:"Auto-created from the source stream if not provided"}),(0,d.jsxs)(n.td,{children:[(0,d.jsx)(n.code,{children:"c2pa.opened"})," (linked to parent)"]})]})]})]}),"\n",(0,d.jsxs)(n.p,{children:["When configuring intent through ",(0,d.jsx)(n.code,{children:"Context"})," or settings JSON, ",(0,d.jsx)(n.code,{children:"Edit"})," and ",(0,d.jsx)(n.code,{children:"Update"})," are specified as lowercase strings (",(0,d.jsx)(n.code,{children:'"edit"'}),", ",(0,d.jsx)(n.code,{children:'"update"'}),"), and ",(0,d.jsx)(n.code,{children:"Create"})," as an object with the source type: ",(0,d.jsx)(n.code,{children:'{"Create": "digitalCapture"}'}),"."]}),"\n",(0,d.jsx)(n.h3,{id:"c2padigitalsourcetype",children:"C2paDigitalSourceType"}),"\n",(0,d.jsxs)(n.table,{children:[(0,d.jsx)(n.thead,{children:(0,d.jsxs)(n.tr,{children:[(0,d.jsx)(n.th,{children:"Enum value"}),(0,d.jsx)(n.th,{children:"Description"})]})}),(0,d.jsxs)(n.tbody,{children:[(0,d.jsxs)(n.tr,{children:[(0,d.jsx)(n.td,{children:(0,d.jsx)(n.code,{children:"EMPTY"})}),(0,d.jsx)(n.td,{children:"No source type specified. The default value."})]}),(0,d.jsxs)(n.tr,{children:[(0,d.jsx)(n.td,{children:(0,d.jsx)(n.code,{children:"DIGITAL_CAPTURE"})}),(0,d.jsx)(n.td,{children:"Captured from a real-world source using a digital device"})]}),(0,d.jsxs)(n.tr,{children:[(0,d.jsx)(n.td,{children:(0,d.jsx)(n.code,{children:"TRAINED_ALGORITHMIC_MEDIA"})}),(0,d.jsx)(n.td,{children:"Created by a trained algorithm (for example, generative AI)"})]}),(0,d.jsxs)(n.tr,{children:[(0,d.jsx)(n.td,{children:(0,d.jsx)(n.code,{children:"DIGITAL_CREATION"})}),(0,d.jsx)(n.td,{children:"Created digitally (for example, drawing software)"})]}),(0,d.jsxs)(n.tr,{children:[(0,d.jsx)(n.td,{children:(0,d.jsx)(n.code,{children:"COMPOSITE_WITH_TRAINED_ALGORITHMIC_MEDIA"})}),(0,d.jsx)(n.td,{children:"Composite that includes trained algorithmic media"})]}),(0,d.jsxs)(n.tr,{children:[(0,d.jsx)(n.td,{children:(0,d.jsx)(n.code,{children:"ALGORITHMICALLY_ENHANCED"})}),(0,d.jsx)(n.td,{children:"Enhanced by an algorithm"})]}),(0,d.jsxs)(n.tr,{children:[(0,d.jsx)(n.td,{children:(0,d.jsx)(n.code,{children:"SCREEN_CAPTURE"})}),(0,d.jsx)(n.td,{children:"Captured from a screen"})]}),(0,d.jsxs)(n.tr,{children:[(0,d.jsx)(n.td,{children:(0,d.jsx)(n.code,{children:"VIRTUAL_RECORDING"})}),(0,d.jsx)(n.td,{children:"Recorded from a virtual environment"})]}),(0,d.jsxs)(n.tr,{children:[(0,d.jsx)(n.td,{children:(0,d.jsx)(n.code,{children:"COMPOSITE"})}),(0,d.jsx)(n.td,{children:"Composed from multiple sources"})]}),(0,d.jsxs)(n.tr,{children:[(0,d.jsx)(n.td,{children:(0,d.jsx)(n.code,{children:"COMPOSITE_CAPTURE"})}),(0,d.jsx)(n.td,{children:"Composite of captured sources"})]}),(0,d.jsxs)(n.tr,{children:[(0,d.jsx)(n.td,{children:(0,d.jsx)(n.code,{children:"COMPOSITE_SYNTHETIC"})}),(0,d.jsx)(n.td,{children:"Composite of synthetic sources"})]}),(0,d.jsxs)(n.tr,{children:[(0,d.jsx)(n.td,{children:(0,d.jsx)(n.code,{children:"DATA_DRIVEN_MEDIA"})}),(0,d.jsx)(n.td,{children:"Generated from data"})]}),(0,d.jsxs)(n.tr,{children:[(0,d.jsx)(n.td,{children:(0,d.jsx)(n.code,{children:"ALGORITHMIC_MEDIA"})}),(0,d.jsx)(n.td,{children:"Created by an algorithm"})]}),(0,d.jsxs)(n.tr,{children:[(0,d.jsx)(n.td,{children:(0,d.jsx)(n.code,{children:"HUMAN_EDITS"})}),(0,d.jsx)(n.td,{children:"Human-edited content"})]}),(0,d.jsxs)(n.tr,{children:[(0,d.jsx)(n.td,{children:(0,d.jsx)(n.code,{children:"COMPUTATIONAL_CAPTURE"})}),(0,d.jsx)(n.td,{children:"Captured with computational processing"})]}),(0,d.jsxs)(n.tr,{children:[(0,d.jsx)(n.td,{children:(0,d.jsx)(n.code,{children:"NEGATIVE_FILM"})}),(0,d.jsx)(n.td,{children:"Scanned from negative film"})]}),(0,d.jsxs)(n.tr,{children:[(0,d.jsx)(n.td,{children:(0,d.jsx)(n.code,{children:"POSITIVE_FILM"})}),(0,d.jsx)(n.td,{children:"Scanned from positive film"})]}),(0,d.jsxs)(n.tr,{children:[(0,d.jsx)(n.td,{children:(0,d.jsx)(n.code,{children:"PRINT"})}),(0,d.jsx)(n.td,{children:"Scanned from a print"})]}),(0,d.jsxs)(n.tr,{children:[(0,d.jsx)(n.td,{children:(0,d.jsx)(n.code,{children:"TRAINED_ALGORITHMIC_DATA"})}),(0,d.jsx)(n.td,{children:"Data created by a trained algorithm"})]})]})]}),"\n",(0,d.jsx)(n.h2,{id:"choosing-the-right-intent",children:"Choosing the right intent"}),"\n",(0,d.jsx)(n.mermaid,{value:'flowchart TD\n    Start([Start]) --\x3e HasParent{Does the asset have\n    prior history?}\n    HasParent --\x3e |No| IsNew[Brand-new content]\n    IsNew --\x3e CREATE["Use Create\n    + C2paDigitalSourceType"]\n    HasParent --\x3e |Yes| ContentChanged{Will the content\n    itself change?}\n    ContentChanged --\x3e |Yes| EDIT[Use Edit]\n    ContentChanged --\x3e |No, metadata only| UPDATE[Use Update]\n    ContentChanged --\x3e |Need full manual control| MANUAL["Skip intents.\n    Define actions and ingredients\n    directly in manifest JSON."]'}),"\n",(0,d.jsx)(n.h2,{id:"create-intent",children:"Create intent"}),"\n",(0,d.jsxs)(n.p,{children:["Use the ",(0,d.jsx)(n.code,{children:"Create"})," intent when the asset has no prior history. A ",(0,d.jsx)(n.code,{children:"C2paDigitalSourceType"})," is required to describe how the asset was produced. ",(0,d.jsx)(n.code,{children:"Builder"})," will:"]}),"\n",(0,d.jsxs)(n.ul,{children:["\n",(0,d.jsxs)(n.li,{children:["Add a ",(0,d.jsx)(n.code,{children:"c2pa.created"})," action with the specified digital source type."]}),"\n",(0,d.jsxs)(n.li,{children:["Reject the operation if a ",(0,d.jsx)(n.code,{children:"parentOf"})," ingredient exists."]}),"\n"]}),"\n",(0,d.jsx)(n.h3,{id:"example-new-digital-creation",children:"Example: New digital creation"}),"\n",(0,d.jsxs)(n.p,{children:["Using ",(0,d.jsx)(n.code,{children:"Context"}),":"]}),"\n",(0,d.jsx)(n.pre,{children:(0,d.jsx)(n.code,{className:"language-py",children:'ctx = Context.from_dict({\n    "builder": {"intent": {"Create": "digitalCreation"}}\n})\n\nwith Builder({}, context=ctx) as builder:\n    with open("source.jpg", "rb") as source, open("output.jpg", "wb") as dest:\n        builder.sign(signer, "image/jpeg", source, dest)\n'})}),"\n",(0,d.jsxs)(n.p,{children:["Using ",(0,d.jsx)(n.code,{children:"set_intent"}),":"]}),"\n",(0,d.jsx)(n.pre,{children:(0,d.jsx)(n.code,{className:"language-py",children:'with Builder({}) as builder:\n    builder.set_intent(\n        C2paBuilderIntent.CREATE,\n        C2paDigitalSourceType.DIGITAL_CREATION,\n    )\n    with open("source.jpg", "rb") as source, open("output.jpg", "wb") as dest:\n        builder.sign(signer, "image/jpeg", source, dest)\n'})}),"\n",(0,d.jsx)(n.h3,{id:"example-marking-ai-generated-content",children:"Example: Marking AI-generated content"}),"\n",(0,d.jsx)(n.pre,{children:(0,d.jsx)(n.code,{className:"language-py",children:'ctx = Context.from_dict({\n    "builder": {"intent": {"Create": "trainedAlgorithmicMedia"}}\n})\n\nwith Builder({}, context=ctx) as builder:\n    with open("ai_output.jpg", "rb") as source, open("signed_ai_output.jpg", "wb") as dest:\n        builder.sign(signer, "image/jpeg", source, dest)\n'})}),"\n",(0,d.jsx)(n.h3,{id:"example-create-with-additional-manifest-metadata",children:"Example: Create with additional manifest metadata"}),"\n",(0,d.jsxs)(n.p,{children:["A ",(0,d.jsx)(n.code,{children:"Context"})," and a manifest definition can be combined. The ",(0,d.jsx)(n.code,{children:"Context"})," handles the intent; the manifest definition provides additional metadata and assertions:"]}),"\n",(0,d.jsx)(n.pre,{children:(0,d.jsx)(n.code,{className:"language-py",children:'ctx = Context.from_dict({\n    "builder": {\n        "intent": {"Create": "digitalCapture"},\n        "claim_generator_info": {"name": "an_app", "version": "0.1.0"},\n    }\n})\n\nmanifest_def = {\n    "title": "My New Image",\n    "assertions": [\n        {\n            "label": "cawg.training-mining",\n            "data": {\n                "entries": {\n                    "cawg.ai_inference": {"use": "notAllowed"},\n                    "cawg.ai_generative_training": {"use": "notAllowed"},\n                }\n            },\n        }\n    ],\n}\n\nwith Builder(manifest_def, context=ctx) as builder:\n    with open("photo.jpg", "rb") as source, open("signed_photo.jpg", "wb") as dest:\n        builder.sign(signer, "image/jpeg", source, dest)\n'})}),"\n",(0,d.jsx)(n.h2,{id:"edit-intent",children:"Edit intent"}),"\n",(0,d.jsxs)(n.p,{children:["Use the ",(0,d.jsx)(n.code,{children:"Edit"})," intent when an existing asset is modified. With this intent, ",(0,d.jsx)(n.code,{children:"Builder"}),":"]}),"\n",(0,d.jsxs)(n.ol,{children:["\n",(0,d.jsxs)(n.li,{children:["Checks if a ",(0,d.jsx)(n.code,{children:"parentOf"})," ingredient has already been added. If not, it automatically creates one from the source stream passed to ",(0,d.jsx)(n.code,{children:"sign()"}),"."]}),"\n",(0,d.jsxs)(n.li,{children:["Adds a ",(0,d.jsx)(n.code,{children:"c2pa.opened"})," action linked to the parent ingredient."]}),"\n"]}),"\n",(0,d.jsxs)(n.p,{children:["No ",(0,d.jsx)(n.code,{children:"digital_source_type"})," parameter is needed."]}),"\n",(0,d.jsx)(n.h3,{id:"example-editing-an-asset",children:"Example: Editing an asset"}),"\n",(0,d.jsxs)(n.p,{children:["Using ",(0,d.jsx)(n.code,{children:"Context"}),":"]}),"\n",(0,d.jsx)(n.pre,{children:(0,d.jsx)(n.code,{className:"language-py",children:'ctx = Context.from_dict({"builder": {"intent": "edit"}})\n\nwith Builder({}, context=ctx) as builder:\n    # The Builder reads "original.jpg" as the parent ingredient,\n    # then writes the new manifest into "edited.jpg"\n    with open("original.jpg", "rb") as source, open("edited
1.jpg", "wb") as dest:\n        builder.sign(signer, "image/jpeg", source, dest)\n'})}),"\n",(0,d.jsxs)(n.p,{children:["Using ",(0,d.jsx)(n.code,{children:"set_intent"}),":"]}),"\n",(0,d.jsx)(n.pre,{children:(0,d.jsx)(n.code,{className:"language-py",children:'with Builder({}) as builder:\n    builder.set_intent(C2paBuilderIntent.EDIT)\n    with open("original.jpg", "rb") as source, open("edited.jpg", "wb") as dest:\n        builder.sign(signer, "image/jpeg", source, dest)\n'})}),"\n",(0,d.jsxs)(n.p,{children:["The resulting manifest contains one ingredient with ",(0,d.jsx)(n.code,{children:'relationship: "parentOf"'})," pointing to ",(0,d.jsx)(n.code,{children:"original.jpg"})," and a ",(0,d.jsx)(n.code,{children:"c2pa.opened"})," action referencing that ingredient. If the source file already has a C2PA manifest, the ingredient preserves the full provenance chain."]}),"\n",(0,d.jsx)(n.h3,{id:"example-editing-with-a-manually-added-parent",children:"Example: Editing with a manually-added parent"}),"\n",(0,d.jsx)(n.p,{children:"To control the parent ingredient's metadata (for example, to set a title or use a different source), add it explicitly:"}),"\n",(0,d.jsx)(n.pre,{children:(0,d.jsx)(n.code,{className:"language-py",children:'ctx = Context.from_dict({"builder": {"intent": "edit"}})\n\nwith Builder({}, context=ctx) as builder:\n    with open("original.jpg", "rb") as original:\n        builder.add_ingredient(\n            {"title": "Original Photo", "relationship": "parentOf"},\n            "image/jpeg",\n            original,\n        )\n\n    with open("canvas.jpg", "rb") as source, open("edited.jpg", "wb") as dest:\n        builder.sign(signer, "image/jpeg", source, dest)\n'})}),"\n",(0,d.jsx)(n.h3,{id:"example-editing-with-additional-component-ingredients",children:"Example: Editing with additional component ingredients"}),"\n",(0,d.jsxs)(n.p,{children:["A parent ingredient can be combined with component or input ingredients. The intent creates the ",(0,d.jsx)(n.code,{children:"c2pa.opened"})," action for the parent; additional actions can reference components (",(0,d.jsx)(n.code,{children:"componentOf"}),") or inputs (",(0,d.jsx)(n.code,{children:"inputTo"}),"):"]}),"\n",(0,d.jsx)(n.pre,{children:(0,d.jsx)(n.code,{className:"language-py",children:'ctx = Context.from_dict({"builder": {"intent": "edit"}})\n\nwith Builder({\n    "assertions": [\n        {\n            "label": "c2pa.actions.v2",\n            "data": {\n                "actions": [\n                    {\n                        "action": "c2pa.placed",\n                        "parameters": {"ingredientIds": ["overlay_label"]},\n                    }\n                ]\n            },\n        }\n    ],\n}, context=ctx) as builder:\n\n    # The Builder auto-creates a parent from the source stream\n    # and generates a c2pa.opened action for it.\n\n    # Add a component ingredient manually.\n    with open("overlay.png", "rb") as overlay:\n        builder.add_ingredient(\n            {\n                "title": "overlay.png",\n                "relationship": "componentOf",\n                "label": "overlay_label",\n            },\n            "image/png",\n            overlay,\n        )\n\n    with open("original.jpg", "rb") as source, open("composite.jpg", "wb") as dest:\n        builder.sign(signer, "image/jpeg", source, dest)\n'})}),"\n",(0,d.jsx)(n.h2,{id:"update-intent",children:"Update intent"}),"\n",(0,d.jsxs)(n.p,{children:["Use the ",(0,d.jsx)(n.code,{children:"Update"})," intent for metadata-only changes where the asset content itself is not modified. This is a restricted form of the ",(0,d.jsx)(n.code,{children:"Edit"})," intent that:"]}),"\n",(0,d.jsxs)(n.ul,{children:["\n",(0,d.jsx)(n.li,{children:"Allows exactly one ingredient (the parent)."}),"\n",(0,d.jsx)(n.li,{children:"Does not allow changes to the parent's hashed content."}),"\n",(0,d.jsxs)(n.li,{children:["Produces a more compact manifest than ",(0,d.jsx)(n.code,{children:"Edit"}),"."]}),"\n"]}),"\n",(0,d.jsxs)(n.p,{children:["As with ",(0,d.jsx)(n.code,{children:"Edit"})," intent, ",(0,d.jsx)(n.code,{children:"Builder"})," automatically creates a parent ingredient from the source stream if one is not provided."]}),"\n",(0,d.jsx)(n.h3,{id:"example-adding-metadata-to-a-signed-asset",children:"Example: Adding metadata to a signed asset"}),"\n",(0,d.jsxs)(n.p,{children:["Using ",(0,d.jsx)(n.code,{children:"Context"}),":"]}),"\n",(0,d.jsx)(n.pre,{children:(0,d.jsx)(n.code,{className:"language-py",children:'ctx = Context.from_dict({"builder": {"intent": "update"}})\n\nwith Builder({}, context=ctx) as builder:\n    with open("signed_asset.jpg", "rb") as source, open("updated_asset.jpg", "wb") as dest:\n        builder.sign(signer, "image/jpeg", source, dest)\n'})}),"\n",(0,d.jsxs)(n.p,{children:["Using ",(0,d.jsx)(n.code,{children:"set_intent"}),":"]}),"\n",(0,d.jsx)(n.pre,{children:(0,d.jsx)(n.code,{className:"language-py",children:'with Builder({}) as builder:\n    builder.set_intent(C2paBuilderIntent.UPDATE)\n\n    with open("signed_asset.jpg", "rb") as source, open("updated_asset.jpg", "wb") as dest:\n        builder.sign(signer, "image/jpeg", source, dest)\n'})})]})}function h(e={}){const{wrapper:n}={...(0,s.R)(),...e.components};return n?(0,d.jsx)(n,{...e,children:(0,d.jsx)(o,{...e})}):o(e)}},8453:(e,n,t)=>{t.d(n,{R:()=>r,x:()=>a});var i=t(6540);const d={},s=i.createContext(d);function r(e){const n=i.useContext(s);return i.useMemo(function(){return"function"==typeof e?e(n):{...n,...e}},[n,e])}function a(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(d):e.components||d:r(e.components),i.createElement(s.Provider,{value:n},e.children)}}}]);

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.