MCPcopy Create free account
hub / github.com/adcontextprotocol/adcp / attachC2PAIfEnabled

Function attachC2PAIfEnabled

server/src/services/illustration-generator.ts:198–241  ·  view source on GitHub ↗
(
  result: { imageBuffer: Buffer; promptUsed: string },
  manifest: { title: string; category?: string; editionDate?: string },
)

Source from the content-addressed store, hash-verified

196 * via notifySystemError) so sustained failures surface rather than hiding in logs.
197 */
198export async function attachC2PAIfEnabled(
199 result: { imageBuffer: Buffer; promptUsed: string },
200 manifest: { title: string; category?: string; editionDate?: string },
201): Promise<GenerateIllustrationResult> {
202 if (!isC2PASigningEnabled()) return result;
203 try {
204 // Re-encode to PNG before signing. Gemini's image model sometimes returns
205 // WebP/JPEG variants that c2pa-node rejects with "type is unsupported";
206 // normalizing through sharp guarantees the bytes match the image/png
207 // mimeType declared to the signer and matches what the portrait path does.
208 // failOn:'error' + .rotate() apply EXIF orientation and drop any upstream
209 // metadata so the C2PA manifest is the sole provenance source of truth.
210 const pngBuffer = await sharp(result.imageBuffer, { failOn: 'error' })
211 .rotate()
212 .png()
213 .toBuffer();
214 const signed = signC2PA(pngBuffer, {
215 claimGenerator: 'AAO Illustration Generator',
216 title: manifest.title,
217 softwareAgent: { name: GEMINI_IMAGE_MODEL, version: GEMINI_IMAGE_VERSION },
218 attributes: {
219 ...(manifest.category ? { category: manifest.category } : {}),
220 ...(manifest.editionDate ? { edition_date: manifest.editionDate } : {}),
221 prompt_sha256: createHash('sha256').update(result.promptUsed).digest('hex'),
222 },
223 });
224 return {
225 imageBuffer: signed.signedBuffer,
226 promptUsed: result.promptUsed,
227 c2pa: { signedAt: new Date(), manifestDigest: signed.manifestDigest },
228 };
229 } catch (err) {
230 const errorMessage = err instanceof Error ? err.message : String(err);
231 logger.error({ err, title: manifest.title }, 'C2PA signing failed');
232 notifySystemError({
233 source: 'c2pa-illustration-signing',
234 errorMessage: `Illustration signing failed for "${manifest.title}": ${errorMessage}`,
235 });
236 if (process.env.C2PA_STRICT === 'true') {
237 throw err;
238 }
239 return result;
240 }
241}

Callers 2

generateIllustrationFunction · 0.85

Calls 4

isC2PASigningEnabledFunction · 0.85
signC2PAFunction · 0.85
notifySystemErrorFunction · 0.85
updateMethod · 0.80

Tested by

no test coverage detected