1"use strict";(globalThis.webpackChunkopensource_contentauth_org=globalThis.webpackChunkopensource_contentauth_org||[]).push([[5598],{4865:(e,n,t)=>{t.d(n,{A:()=>p});t(6540);var i=t(8215),r=t(7559),s=t(7751),a=t(3104),d=t(2303);const l={tabList:"tabList__CuJ",tabItem:"tabItem_LNqP"};var c=t(4848);function o({className:e}){const{selectedValue:n,selectValue:t,tabValues:r,block:d}=(0,s.uc)(),o=[],{blockElementScrollPositionUntilNextRender:u}=(0,a.a_)(),h=e=>{const i=e.currentTarget,s=o.indexOf(i),a=r[s].value;a!==n&&(u(i),t(a))},p=e=>{let n=null;switch(e.key){case"Enter":h(e);break;case"ArrowRight":{const t=o.indexOf(e.currentTarget)+1;n=o[t]??o[0];break}case"ArrowLeft":{const t=o.indexOf(e.currentTarget)-1;n=o[t]??o[o.length-1];break}}n?.focus()};return(0,c.jsx)("ul",{role:"tablist","aria-orientation":"horizontal",className:(0,i.A)("tabs",{"tabs--block":d},e),children:r.map(({value:e,label:t,attributes:r})=>(0,c.jsx)("li",{role:"tab",tabIndex:n===e?0:-1,"aria-selected":n===e,ref:e=>{o.push(e)},onKeyDown:p,onClick:h,...r,className:(0,i.A)("tabs__item",l.tabItem,r?.className,{"tabs__item--active":n===e}),children:t??e},e))})}function u({children:e}){return(0,c.jsx)("div",{className:"margin-top--md",children:e})}function h({className:e,children:n}){return(0,c.jsxs)("div",{className:(0,i.A)(r.G.tabs.container,"tabs-container",l.tabList),
1children:[(0,c.jsx)(o,{className:e}),(0,c.jsx)(u,{children:n})]})}function p(e){const n=(0,d.A)(),t=(0,s.OC)(e);return(0,c.jsx)(s.O_,{value:t,children:(0,c.jsx)(h,{className:e.className,children:(0,s.vT)(e.children)})},String(n))}},5263:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>v,contentTitle:()=>f,default:()=>C,frontMatter:()=>b,metadata:()=>i,toc:()=>w});const i=JSON.parse('{"id":"tasks/intents","title":"Using builder intents","description":"Intents tell the Builder what kind of manifest you are creating. They enable validation, add required default actions, and help prevent invalid operations.","source":"@site/docs/tasks/intents.mdx","sourceDirName":"tasks","slug":"/tasks/intents","permalink":"/docs/tasks/intents","draft":false,"unlisted":false,"editUrl":"https://github.com/contentauth/opensource.contentauth.org/edit/main/docs/tasks/intents.mdx","tags":[],"version":"current","frontMatter":{"id":"intents","title":"Using builder intents","hide_table_of_contents":true},"sidebar":"docs","previous":{"title":"Getting manifest resources","permalink":"/docs/tasks/get-resources"},"next":{"title":"Using working stores and archives","permalink":"/docs/tasks/archives"}}');var r=t(4848),s=t(8453),a=t(4865),d=t(9365);function l(e){const n={code:"code",h3:"h3",p:"p",pre:"pre",...(0,s.R)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(n.h3,{id:"setting-the-intent",children:"Setting the intent"}),"\n",(0,r.jsxs)(n.p,{children:["Set the intent through ",(0,r.jsx)(n.code,{children:"Context"})," settings or by calling ",(0,r.jsx)(n.code,{children:"set_intent"})," on the ",(0,r.jsx)(n.code,{children:"Builder"}),". Using ",(0,r.jsx)(n.code,{children:"Context"})," keeps intent configuration alongside other builder settings:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-rust",children:'use c2pa::{Context, Builder, Result};\n\nfn main() -> Result<()> {\n let context = Context::new()\n .with_settings(r#"{\n "builder": {\n "intent": {"Create": "digitalCapture"},\n "claim_generator_info": {"name": "My App", "version": "1.0"}\n }\n }"#)?;\n\n let mut builder = Builder::from_context(context)\n .with_definition(r#"{"title": "New Image"}"#)?;\n\n let mut source = std::fs::File::open("source.jpg")?;\n let mut dest = std::fs::File::create("signed.jpg")?;\n builder.save_to_stream("image/jpeg", &mut source, &mut dest)?;\n Ok(())\n}\n'})}),"\n",(0,r.jsxs)(n.p,{children:["Alternatively, call ",(0,r.jsx)(n.code,{children:"set_intent"})," directly on the ",(0,r.jsx)(n.code,{children:"Builder"}),":"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-rust",children:"use c2pa::{Builder, BuilderIntent, DigitalSourceType};\n\nbuilder.set_intent(BuilderIntent::Create(DigitalSourceType::DigitalCapture));\n"})}),"\n",(0,r.jsx)(n.h3,{id:"create-intent",children:"Create intent"}),"\n",(0,r.jsxs)(n.p,{children:["Use ",(0,r.jsx)(n.code,{children:"BuilderIntent::Create(DigitalSourceType)"})," for new digital creations without a parent ingredient. A ",(0,r.jsx)(n.code,{children:"DigitalSourceType"})," is required; common values include ",(0,r.jsx)(n.code,{children:"Empty"}),", ",(0,r.jsx)(n.code,{children:"DigitalCapture"}),", ",(0,r.jsx)(n.code,{children:"TrainedAlgorithmicMedia"}),", and ",(0,r.jsx)(n.code,{children:"DigitalCreation"}),"."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-rust",children:"builder.set_intent(BuilderIntent::Create(DigitalSourceType::TrainedAlgorithmicMedia));\n"})}),"\n",(0,r.jsx)(n.h3,{id:"edit-intent",children:"Edit intent"}),"\n",(0,r.jsxs)(n.p,{children:["Use ",(0,r.jsx)(n.code,{children:"BuilderIntent::Edit"})," for editing an existing asset. If no parent ingredient has been added, the ",(0,r.jsx)(n.code,{children:"Builder"})," automatically derives one from the source stream:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-rust",children:'use serde_json::json;\n\nbuilder.set_intent(BuilderIntent::Edit);\nbuilder.add_ingredient_from_stream(\n json!({"title": "Original", "relationship": "parentOf"}).to_string(),\n "image/jpeg",\n &mut source_stream,\n)?;\n'})}),"\n",(0,r.jsx)(n.h3,{id:"update-intent",children:"Update intent"}),"\n",(0,r.jsxs)(n.p,{children:["Use ",(0,r.jsx)(n.code,{children:"BuilderIntent::Update"})," for non-editorial, metadata-only changes. It allows exactly one ingredient (the parent) and does not allow changes to the parent's hashed content:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-rust",children:"builder.set_intent(BuilderIntent::Update);\n"})})]})}function c(e={}){const{wrapper:n}={...(0,s.R)(),...e.components};return n?(0,r.jsx)(n,{...e,children:(0,r.jsx)(l,{...e})}):l(e)}function o(e){const n={code:"code",h3:"h3",p:"p",pre:"pre",...(0,s.R)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(n.h3,{id:"setting-the-intent",children:"Setting the intent"}),"\n",(0,r.jsxs)(n.p,{children:["Set the intent through ",(0,r.jsx)(n.code,{children:"Context"})," settings or by calling ",(0,r.jsx)(n.code,{children:"set_intent"})," on the ",(0,r.jsx)(n.code,{children:"Builder"}),". Using ",(0,r.jsx)(n.code,{children:"Context"})," keeps intent configuration alongside other builder settings:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-cpp",children:'#include "c2pa.hpp"\n\nc2pa::Context context(R"({\n "version": 1,\n "builder": {\n "intent": {"Create": "digitalCapture"},\n "claim_generator_info": {"name": "My App", "version": "1.0"}\n }\n})");\n\nc2pa::Builder builder(context, R"({})");\nbuilder.sign(source_path, output_path, signer);\n'})}),"\n",(0,r.jsxs)(n.p,{children:["Alternatively, call ",(0,r.jsx)(n.code,{children:"set_intent"})," directly on the ",(0,r.jsx)(n.code,{children:"Builder"}),":"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-cpp",children:'c2pa::Context context;\nc2pa::Builder builder(context, R"({})");\nbuilder.set_intent(Create, DigitalCapture);\nbuilder.sign(source_path, output_path, signer);\n'})}),"\n",(0,r.jsx)(n.h3,{id:"create-intent",children:"Create intent"}),"\n",(0,r.jsxs)(n.p,{children:["Use the ",(0,r.jsx)(n.code,{children:"Create"})," intent for new digital creations without a parent ingredient. A ",(0,r.jsx)(n.code,{children:"C2paDigitalSourceType"})," is required; common values include ",(0,r.jsx)(n.code,{children:"Empty"}),", ",(0,r.jsx)(n.code,{children:"DigitalCapture"}),", ",(0,r.jsx)(n.code,{children:"TrainedAlgorithmicMedia"}),", and ",(0,r.jsx)(n.code,{children:"DigitalCreation"}),"."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-cpp",children:'c2pa::Context context(R"({\n "version": 1,\n "builder": {"intent": {"Create": "trainedAlgorithmicMedia"}}\n})");\n\nc2pa::Builder builder(context, R"({})");\nbuilder.sign(source_path, output_path, signer);\n'})}),"\n",(0,r.jsx)(n.h3,{id:"edit-intent",children:"Edit intent"}),"\n",(0,r.jsxs)(n.p,{children:["Use the ",(0,r.jsx)(n.code,{children:"Edit"})," intent for editing an existing asset. If no parent ingredient has been added, the ",(0,r.jsx)(n.code,{children:"Builder"})," automatically creates one from the source stream passed to ",(0,r.jsx)(n.code,{children:"sign()"}),":"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-cpp",children:'c2pa::Context context(R"({\n "version": 1,\n "builder": {"intent": "edit"}\n})");\n\nc2pa::Builder builder(context, R"({})");\nbuilder.sign("original.jpg", "edited.jpg", signer);\n'})}),"\n",(0,r.jsx)(n.p,{children:"To manually provide the parent ingredient:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-cpp",children:'c2pa::Context context(R"({\n "version": 1,\n "builder": {"intent": "edit"}\n})");\n\nc2pa::Builder builder(context, R"({})");\n\nstd::ifstream original("original.jpg", std::ios::binary);\nbuilder.add_ingredient(\n R"({"title": "Original Photo", "relationship": "parentOf"})",\n "image/jpeg",\n original\n);\n\nbuilder.sign("canvas.jpg", "edited.jpg", signer);\n'})}),"\n",(0,r.jsx)(n.h3,{id:"update-intent",children:"Update intent"}),"\n",(0,r.jsxs)(n.p,{children:["Use the ",(0,r.jsx)(n.code,{children:"Update"})," intent for non-editorial, metadata-only changes. It allows exactly one ingredient (the parent) and does not allow changes to the parent's hashed content:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-cpp",children:'c2pa::Context context(R"({\n "version": 1,\n "builder": {"intent": "update"}\n})");\n\nc2pa::Builder builder(context, R"({})");\nbuilder.sign("signed_asset.jpg", "updated_asset.jpg", signer);\n'})})]})}function u(e={}){const{wrapper:n}={...(0,s.R)(),...e.components};return n?(0,r.jsx)(n,{...e,children:(0,r.jsx)(o,{...e})}):o(e)}function h(e){const n={code:"code",h3:"h3",p:"p",pre:"pre",...(0,s.R)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(n.h3,{id:"setting-the-intent",children:"Setting the intent"}),"\n",(0,r.jsxs)(n.p,{children:["Set the intent through ",(0,r.jsx)(n.code,{children:"Context"})," settings. Using ",(0,r.jsx)(n.code,{children:"Context"})," keeps intent configuration alongside other builder settings:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.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": "1.0"}\n }\n})\n\nbuilder = Builder(manifest_json, context=ctx)\n\nwith open("source.jpg", "rb") as src, open("signed.jpg", "w+b") as dst:\n builder.sign(signer, "image/jpeg", src, dst)\n'})}),"\n",(0,r.jsxs)(n.p,{children:["Alternatively, you can call ",(0,r.jsx)(n.code,{children:"set_intent"})," directly on a ",(0,r.jsx)(n.code,{children:"Builder"})," instance for one-off operations or when the intent is determined at runtime. For example:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.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,r.jsx)(n.h3,{id:"create-intent",children:"Create intent"}),"\n",(0,r.jsxs)(n.p,{children:["Use the ",(0,r.jsx)(n.code,{children:"Create"})," intent for new digital creations without a parent ingredient. A digital source type is required; common values include ",(0,r.jsx)(n.code,{children:'"digitalCapture"'}),", ",(0,r.jsx)(n.code,{children:'"trainedAlgorithmicMedia"'}),", and ",(0,r.jsx)(n.code,{children:'"digitalCreation"'}),"."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-py",children:'ctx = Context.from_dict({\n "builder": {"intent": {"Create": "trainedAlgorithmicMedia"}}\n})\n\nbuilder = Builder(manifest_json, context=ctx)\nwith open("source.jpg", "rb") as src, open("signed.jpg", "w+b") as dst:\n builder.sign(signer, "image/jpeg", src, dst)\n'})}),"\n",(0,r.jsx)(n.h3,{id:"edit-intent",children:"Edit intent"}),"\n",(0,r.jsxs)(n.p,{children:["Use the ",(0,r.jsx)(n.code,{children:"Edit"})," intent for editing an existing asset. If no parent ingredient has been added, the ",(0,r.jsx)(n.code,{children:"Builder"})," automatically creates one from the source stream passed to ",(0,r.jsx)(n.code,{children:"sign()"}),":"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-py",children:'ctx = Context.from_dict({\n "builder": {"intent": "edit"}\n})\n\nbuilder = Builder(manifest_json, context=ctx)\nwith open("original.jpg", "rb") as src, open("edited.jpg", "w+b") as dst:\n builder.sign(signer, "image/jpeg", src, dst)\n'})}),"\n",(0,r.jsx)(n.p,{children:"To manually provide the parent ingredient:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-py",children:'import json\n\nctx = Context.from_dict({\n "builder": {"intent": "edit"}\n})\n\nbuilder = Builder(manifest_json, context=ctx)\n\ningredient_json = json.dumps({\n "title": "Original Photo",\n "relationship": "parentOf"\n})\nwith open("original.jpg", "rb") as ingredient:\n builder.add_ingredient(ingredient_json, "image/jpeg", ingredient)\n\nwith open("canvas.jpg", "rb") as src, open("edited.jpg", "w+b") as dst:\n builder.sign(signer, "image/jpeg", src, dst)\n'})}),"\n",(0,r.jsx)(n.h3,{id:"update-intent",children:"Update intent"}),"\n",(0,r.jsxs)(n.p,{children:["Use the ",(0,r.jsx)(n.code,{children:"Update"})," intent for non-editorial, metadata-only changes. It allows exactly one ingredient (the parent) and does not allow changes to the parent's hashed content:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-py",children:'ctx = Context.from_dict({\n "builder": {"intent": "update"}\n})\n\nbuilder = Builder(manifest_json, context=ctx)\nwith open("signed_asset.jpg", "rb") as src, open("updated.jpg", "w+b") as dst:\n builder.sign(signer, "image/jpeg", src, dst)\n'})})]})}function p(e={}){const{wrapper:n}={...(0,s.R)(),...e.components};return n?(0,r.jsx)(n,{...e,children:(0,r.jsx)(h,{...e})}):h(e)}function g(e){const n={a:"a",code:"code",h3:"h3",p:"p",pre:"pre",strong:"strong",...(0,s.R)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(n.h3,{id:"setting-the-intent",children:"Setting the intent"}),"\n",(0,r.jsxs)(n.p,{children:["The snippets below use ",(0,r.jsx)(n.code,{children:"c2pa"})," from ",(0,r.jsx)(n.code,{children:"const c2pa = await createC2pa({ wasmSrc });"})," (see ",(0,r.jsx)(n.a,{href:"/docs/tasks/read",children:"Reading and verifying manifest data"}),")."]}),"\n",(0,r.jsxs)(n.p,{children:["Call ",(0,r.jsx)(n.a,{href:"https://contentauth.github.io/c2pa-js/interfaces/_contentauth_c2pa-web.Builder.html#setintent",children:(0,r.jsx)(n.code,{children:"setIntent"})})," on a builder from ",(0,r.jsx)(n.code,{children:"c2pa.builder"}),". Intents match the same ",(0,r.jsx)(n.strong,{children:"Create"})," / ",(0,r.jsx)(n.strong,{children:"Edit"})," / ",(0,r.jsx)(n.strong,{children:"Update"})," semantics as other CAI SDKs (see the table on this page)."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-typescript",children:"const builder = await c2pa.builder.new();\n\nawait builder.setIntent({\n create:\n 'http://cv.iptc.org/newscodes/
1digitalsourcetype/trainedAlgorithmicMedia',\n});\n\nawait builder.setIntent('edit');\n\nawait builder.setIntent('update');\n"})}),"\n",(0,r.jsx)(n.h3,{id:"create-intent",children:"Create intent"}),"\n",(0,r.jsxs)(n.p,{children:["Use ",(0,r.jsx)(n.code,{children:"create"})," with a ",(0,r.jsx)(n.a,{href:"https://c2pa.org/specifications/specifications/2.2/specs/C2PA_Specification.html#_digital_source_type",children:"digital source type"})," URI. There must be no parent ingredient; the SDK may add ",(0,r.jsx)(n.code,{children:"c2pa.created"})," when appropriate."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-typescript",children:"const builder = await c2pa.builder.new();\n\nawait builder.setIntent({\n create:\n 'http://cv.iptc.org/newscodes/digitalsourcetype/digitalCapture',\n});\n// Add assertions, thumbnail, then sign (see [Build](../build.mdx)).\n"})}),"\n",(0,r.jsx)(n.h3,{id:"edit-intent",children:"Edit intent"}),"\n",(0,r.jsxs)(n.p,{children:["Use ",(0,r.jsx)(n.code,{children:"edit"})," when changing pixel or editorial content. If you do not add a parent ingredient, one can be derived from the source blob you pass to ",(0,r.jsx)(n.a,{href:"/docs/tasks/build",children:(0,r.jsx)(n.code,{children:"sign"})}),"."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-typescript",children:"const builder = await c2pa.builder.new();\nawait builder.setIntent('edit');\n"})}),"\n",(0,r.jsxs)(n.p,{children:["Add a parent explicitly with ",(0,r.jsx)(n.a,{href:"https://contentauth.github.io/c2pa-js/interfaces/_contentauth_c2pa-web.Builder.html#addingredientfromblob",children:(0,r.jsx)(n.code,{children:"addIngredientFromBlob"})}),":"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-typescript",children:"const parentBlob = await fetch('/original.jpg').then((r) => r.blob());\nconst builder = await c2pa.builder.new();\nawait builder.setIntent('edit');\n\nawait builder.addIngredientFromBlob(\n {\n title: 'Original Photo',\n relationship: 'parentOf',\n format: 'image/jpeg',\n },\n parentBlob.type,\n parentBlob,\n);\n"})}),"\n",(0,r.jsx)(n.h3,{id:"update-intent",children:"Update intent"}),"\n",(0,r.jsxs)(n.p,{children:["Use ",(0,r.jsx)(n.code,{children:"update"})," for restricted, metadata-oriented edits (single parent ingredient, no change to the parent\u2019s hashed payload per C2PA rules)."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-typescript",children:"const builder = await c2pa.builder.new();\nawait builder.setIntent('update');\n"})}),"\n",(0,r.jsxs)(n.p,{children:["More background: ",(0,r.jsxs)(n.a,{href:"https://docs.rs/c2pa/latest/c2pa/struct.Builder.html",children:["c2pa-rs ",(0,r.jsx)(n.code,{children:"Builder"})]})," and the ",(0,r.jsx)(n.a,{href:"https://github.com/contentauth/c2pa-js/tree/main/packages/c2pa-web#setting-builder-intent",children:"c2pa-web README"}),"."]})]})}function x(e={}){const{wrapper:n}={...(0,s.R)(),...e.components};return n?(0,r.jsx)(n,{...e,children:(0,r.jsx)(g,{...e})}):g(e)}function j(e){const n={a:"a",code:"code",h3:"h3",p:"p",pre:"pre",...(0,s.R)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(n.h3,{id:"setting-the-intent",children:"Setting the intent"}),"\n",(0,r.jsxs)(n.p,{children:["In Node.js, call ",(0,r.jsx)(n.code,{children:"setIntent"})," on a ",(0,r.jsx)(n.code,{children:"Builder"})," from ",(0,r.jsx)(n.code,{children:"@contentauth/c2pa-node"}),". The intent shapes validation, default actions, and whether a parent ingredient is required."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-javascript",children:"import { Builder } from '@contentauth/c2pa-node';\n\nconst builder = Builder.new();\n\n// Runtime intent (Create, Edit, or Update)\nbuilder.setIntent({\n create:\n 'http://cv.iptc.org/newscodes/digitalsourcetype/trainedAlgorithmicMedia',\n});\n"})}),"\n",(0,r.jsxs)(n.p,{children:["You can also set ",(0,r.jsx)(n.code,{children:"edit"})," or ",(0,r.jsx)(n.code,{children:"update"})," with a string:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-javascript",children:"builder.setIntent('edit');\nbuilder.setIntent('update');\n"})}),"\n",(0,r.jsx)(n.h3,{id:"create-intent",children:"Create intent"}),"\n",(0,r.jsxs)(n.p,{children:["Use a ",(0,r.jsx)(n.code,{children:"create"})," intent for new digital creations. You must supply a ",(0,r.jsx)(n.a,{href:"https://c2pa.org/specifications/specifications/2.2/specs/C2PA_Specification.html#_digital_source_type",children:"digital source type"})," URI. The manifest must not have a parent ingredient; the SDK can add a ",(0,r.jsx)(n.code,{children:"c2pa.created"})," action when appropriate."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-javascript",children:"import { Builder, LocalSigner } from '@contentauth/c2pa-node';\nimport { readFile } from 'node:fs/promises';\n\nconst builder = Builder.new();\nbuilder.setIntent({\n create:\n 'http://cv.iptc.org/newscodes/
1digitalsourcetype/digitalCapture',\n});\n\nconst signer = LocalSigner.newSigner(\n await readFile('signer.pem'),\n await readFile('signer.key'),\n 'es256',\n);\n\nbuilder.sign(\n signer,\n { path: 'source.jpg' },\n { path: 'signed.jpg' },\n);\n"})}),"\n",(0,r.jsx)(n.h3,{id:"edit-intent",children:"Edit intent"}),"\n",(0,r.jsxs)(n.p,{children:["Use ",(0,r.jsx)(n.code,{children:"edit"})," when modifying existing content. If you do not add a parent ingredient, one can be created from the source asset you pass to ",(0,r.jsx)(n.code,{children:"sign"}),"."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-javascript",children:"import { Builder } from '@contentauth/c2pa-node';\n\nconst builder = Builder.new();\nbuilder.setIntent('edit');\n"})}),"\n",(0,r.jsxs)(n.p,{children:["To supply the parent explicitly, add an ingredient JSON string and optional asset buffer (see ",(0,r.jsx)(n.a,{href:"/docs/tasks/build",children:"Adding manifest data"}),"):"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-javascript",children:"import { Builder } from '@contentauth/c2pa-node';\nimport { readFile } from 'node:fs/promises';\n\nconst builder = Builder.new();\nbuilder.setIntent('edit');\n\nconst parentJson = JSON.stringify({\n title: 'Original Photo',\n relationship: 'parentOf',\n format: 'image/jpeg',\n});\n\nawait builder.addIngredient(parentJson, {\n buffer: await readFile('original.jpg'),\n mimeType: 'image/jpeg',\n});\n"})}),"\n",(0,r.jsx)(n.h3,{id:"update-intent",children:"Update intent"}),"\n",(0,r.jsxs)(n.p,{children:["Use ",(0,r.jsx)(n.code,{children:"update"})," for restricted, metadata-oriented changes: typically a single parent ingredient and no changes to the parent\u2019s hashed content."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-javascript",children:"import { Builder } from '@contentauth/c2pa-node';\n\nconst builder = Builder.new();\nbuilder.setIntent('update');\n"})}),"\n",(0,r.jsxs)(n.p,{children:["For more detail on intent semantics, see the ",(0,r.jsxs)(n.a,{href:"https://docs.rs/c2pa/latest/c2pa/struct.Builder.html",children:["c2pa-rs ",(0,r.jsx)(n.code,{children:"Builder"})," documentation"]}),"."]})]})}function m(e={}){const{wrapper:n}={...(0,s.R)(),...e.components};return n?(0,r.jsx)(n,{...e,children:(0,r.jsx)(j,{...e})}):j(e)}const b={id:"intents",title:"Using builder intents",hide_table_of_contents:!0},f=void 0,v={},w=[{value:"Intent types",id:"intent-types",level:3},{value:"Setting the intent",id:"setting-the-intent",level:3},{value:"Create intent",id:"create-intent",level:3},{value:"Edit intent",id:"edit-intent",level:3},{value:"Update intent",id:"update-intent",level:3},{value:"Setting the intent",id:"setting-the-intent",level:3},{value:"Create intent",id:"create-intent",level:3},{value:"Edit intent",id:"edit-intent",level:3},{value:"Update intent",id:"update-intent",level:3},{value:"Setting the intent",id:"setting-the-intent",level:3},{value:"Create intent",id:"create-intent",level:3},{value:"Edit intent",id:"edit-intent",level:3},{value:"Update intent",id:"update-intent",level:3},{value:"Setting the intent",id:"setting-the-intent",level:3},{value:"Create intent",id:"create-intent",level:3},{value:"Edit intent",id:"edit-intent",level:3},{value:"Update intent",id:"update-intent",level:3},{value:"Setting the intent",id:"setting-the-intent",level:3},{value:"Create intent",id:"create-intent",level:3},{value:"Edit intent",id:"edit-intent",level:3},{value:"Update intent",id:"update-intent",level:3}];function y(e){const n={code:"code",em:"em",h3:"h3",p:"p",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",...(0,s.R)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.em,{children:"Intents"})," tell the ",(0,r.jsx)(n.code,{children:"Builder"})," what kind of manifest you are creating. They enable validation, add required default actions, and help prevent invalid operations."]}),"\n",(0,r.jsx)(n.h3,{id:"intent-types",children:"Intent types"}),"\n",(0,r.jsx)(n.p,{children:"There are three types of intents, shown here:"}),"\n",(0,r.jsxs)(n.table,{children:[(0,r.jsx)(n.thead,{children:(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.th,{children:"Intent"}),(0,r.jsx)(n.th,{children:"Use when..."}),(0,r.jsx)(n.th,{children:"Parent ingredient"}),(0,r.jsx)(n.th,{children:"Auto-generated action"})]})}),(0,r.jsxs)(n.tbody,{children:[(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:(0,r.jsx)(n.code,{children:"Create"})}),(0,r.jsx)(n.td,{children:"Creating brand-new content"}),(0,r.jsx)(n.td,{children:"Must NOT have one"}),(0,r.jsx)(n.td,{children:(0,r.jsx)(n.code,{children:"c2pa.created"})})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:(0,r.jsx)(n.code,{children:"Edit"})}),(0,r.jsx)(n.td,{children:"Modifying existing content"}),(0,r.jsx)(n.td,{children:"Auto-created from source if not provided"}),(0,r.jsxs)(n.td,{children:[(0,r.jsx)(n.code,{children:"c2pa.opened"})," (linked to parent)"]})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:(0,r.jsx)(n.code,{children:"Update"})}),(0,r.jsx)(n.td,{children:"Making metadata-only changes"}),(0,r.jsx)(n.td,{children:"Auto-created from source if not provided"}),(0,r.jsxs)(n.td,{children:[(0,r.jsx)(n.code,{children:"c2pa.opened"})," (linked to parent)"]})]})]})]}),"\n",(0,r.jsxs)(a.A,{groupId:"programming-lang",queryString:"lang",children:[(0,r.jsx)(d.A,{value:"rust",label:"Rust",children:(0,r.jsx)(c,{name:"rust-intents"})}),(0,r.jsx)(d.A,{value:"cpp",label:"C++",children:(0,r.jsx)(u,{name:"cpp-intents"})}),(0,r.jsx)(d.A,{value:"python",label:"Python",default:!0,children:(0,r.jsx)(p,{name:"python-intents"})}),(0,r.jsx)(d.A,{value:"js",label:"JavaScript",children:(0,r.jsx)(x,{name:"js-intents"})}),(0,r.jsx)(d.A,{value:"node",label:"Node.js",children:(0,r.jsx)(m,{name:"node-intents"})})]})]})}function C(e={}){const{wrapper:n}={...(0,s.R)(),...e.components};return n?(0,r.jsx)(n,{...e,children:(0,r.jsx)(y,{...e})}):y(e)}},7751:(e,n,t)=>{t.d(n,{OC:()=>g,O_:()=>m,uc:()=>j,vT:()=>
1o});var i=t(6540),r=t(6347),s=t(205),a=t(7485),d=t(679),l=t(1682),c=t(4848);function o(e){return i.Children.toArray(e).filter(e=>"\n"!==e)}function u(e){const{values:n,children:t}=e;return(0,i.useMemo)(()=>{const e=n??function(e){return i.Children.toArray(e).flatMap(e=>{if(!e)return[];if((0,i.isValidElement)(e)&&function(e){const{props:n}=e;return!!n&&"object"==typeof n&&"value"in n}(e))return[e];const n="string"==typeof e.type?e.type:e.type.name;throw new Error(`Docusaurus error: Bad <Tabs> child <${n}>: all children of the <Tabs> component should be <TabItem>, and every <TabItem> should have a unique "value" prop.\nIf you do not want to pass on a "value" prop to the direct children of <Tabs>, you can also pass an explicit <Tabs values={...}> prop.`)}).map(({props:{value:e,label:n,attributes:t,default:i}})=>({value:e,label:n,attributes:t,default:i}))}(t);return function(e){const n=(0,l.XI)(e,(e,n)=>e.value===n.value);if(n.length>0)throw new Error(`Docusaurus error: Duplicate values "${n.map(e=>`'${e.value}'`).join(", ")}" found in <Tabs>. Every value needs to be unique.`)}(e),e},[n,t])}function h({value:e,tabValues:n}){return n.some(n=>n.value===e)}function p({queryString:e=!1,groupId:n}){const t=(0,r.W6)(),s=function({queryString:e=!1,groupId:n}){if("string"==typeof e)return e;if(!1===e)return null;if(!0===e&&!n)throw new Error('Docusaurus error: The <Tabs> component groupId prop is required if queryString=true, because this value is used as the search param name. You can also provide an explicit value such as queryString="my-search-param".');return n??null}({queryString:e,groupId:n});return[(0,a.aZ)(s),(0,i.useCallback)(e=>{if(!s)return;const n=new URLSearchParams(t.location.search);n.set(s,e),t.replace({...t.location,search:n.toString()})},[s,t])]}function g(e){const{defaultValue:n,queryString:t=!1,groupId:r}=e,a=u(e),[l,c]=(0,i.useState)(()=>function({defaultValue:e,tabValues:n}){if(0===n.length)throw new Error("Docusaurus error: the <Tabs> component requires at least one <TabItem> children component");if(e){if(!h({value:e,tabValues:n}))throw new Error(`Docusaurus error: The <Tabs> has a defaultValue "${e}" but none of its children has the corresponding value. Available values are: ${n.map(e=>e.value).join(", ")}. If you intend to show no default tab, use defaultValue={null} instead.`);return e}const t=n.find(e=>e.default)??n[0];if(!t)throw new Error("Unexpected error: 0 tabValues");return t.value}({defaultValue:n,tabValues:a})),[o,g]=p({queryString:t,groupId:r}),[x,j]=function({groupId:e}){const n=function(e){return e?`docusaurus.tab.${e}`:null}(e),[t,r]=(0,d.Dv)(n);return[t,(0,i.useCallback)(e=>{n&&r.set(e)},[n,r])]}({groupId:r}),m=(()=>{const e=o??x;return h({value:e,tabValues:a})?e:null})();(0,s.A)(()=>{m&&c(m)},[m]);return{selectedValue:l,selectValue:(0,i.useCallback)(e=>{if(!h({value:e,tabValues:a}))throw new Error(`Can't select invalid tab value=${e}`);c(e),g(e),j(e)},[g,j,a]),tabValues:a,lazy:e.lazy??!1,block:e.block??!1}}const x=(0,i.createContext)(null);function j(){const e=i.useContext(x);if(!e)throw new Error("useTabsContext() must be used within a Tabs component");return e}function m(e){return(0,c.jsx)(x.Provider,{value:e.value,children:e.children})}},8453:(e,n,t)=>{t.d(n,{R:()=>a,x:()=>d});var i=t(6540);const r={},s=i.createContext(r);function a(e){const n=i.useContext(s);return i.useMemo(function(){return"function"==typeof e?e(n):{...n,...e}},[n,e])}function d(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:a(e.components),i.createElement(s.Provider,{value:n},e.children)}},9365:(e,n,t)=>{t.d(n,{A:()=>l});t(6540);var i=t(8215),r=t(7751);const s={tabItem:"tabItem_Ymn6"};var a=t(4848);function d({children:e,className:n,hidden:t}){return(0,a.jsx)("div",{role:"tabpanel",className:(0,i.A)(s.tabItem,n),hidden:t,children:e})}function l({children:e,className:n,value:t}){const{selectedValue:i,lazy:s}=(0,r.uc)(),l=t===i;return!l&&s?null:(0,a.jsx)(d,{className:n,hidden:!l,children:e})}}}]);
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.