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

Function main

scripts/backfill-c2pa-static.ts:54–119  ·  view source on GitHub ↗
()

Source from the content-addressed store, hash-verified

52}
53
54async function main(): Promise<void> {
55 const dryRun = process.argv.includes("--dry-run");
56
57 if (!isC2PASigningEnabled()) {
58 console.error(
59 "C2PA_SIGNING_ENABLED + C2PA_CERT_PEM_B64 + C2PA_PRIVATE_KEY_PEM_B64 must all be set.",
60 );
61 process.exit(1);
62 }
63
64 const files: string[] = [];
65 for (const root of ROOTS) await walk(root, files);
66 files.sort();
67
68 console.log(`Found ${files.length} PNGs under ${ROOTS.join(", ")}.`);
69 if (dryRun) console.log("(dry run — no files will be modified)");
70
71 const stats: BackfillStats = { signed: 0, skippedAlreadySigned: 0, failed: 0 };
72
73 for (const file of files) {
74 const buffer = await fs.promises.readFile(file);
75
76 // Detect actual MIME type from magic bytes — some committed .png files
77 // are really JPEGs with the wrong extension. c2pa-rs rejects a MIME/buffer
78 // mismatch, so we feed it the truth.
79 const detected = await fileTypeFromBuffer(buffer);
80 const mimeType = detected?.mime ?? "image/png";
81 if (!SIGNABLE_MIME_TYPES.has(mimeType)) {
82 console.warn(` ⚠ ${file}: unsupported type ${mimeType}, skipping`);
83 continue;
84 }
85
86 if (await hasEmbeddedManifest(buffer, mimeType)) {
87 stats.skippedAlreadySigned++;
88 continue;
89 }
90 try {
91 const signed = signC2PA(buffer, {
92 claimGenerator: "AAO Docs Storyboard Generator",
93 title: path.basename(file),
94 softwareAgent: { name: "gemini-3.1-flash-image-preview", version: "preview" },
95 mimeType,
96 attributes: {
97 relative_path: path.relative(process.cwd(), file),
98 // Backfilled rows hash the file bytes since the original prompt is
99 // no longer available. The hash still serves as tamper evidence.
100 source_sha256: createHash("sha256").update(buffer).digest("hex"),
101 backfilled: true,
102 },
103 });
104 if (!dryRun) await fs.promises.writeFile(file, signed.signedBuffer);
105 stats.signed++;
106 if (stats.signed % 10 === 0 || stats.signed === files.length) {
107 console.log(` [${stats.signed}/${files.length}] ${file}`);
108 }
109 } catch (err) {
110 console.error(` ✗ ${file}: ${(err as Error).message}`);
111 stats.failed++;

Callers 1

Calls 7

isC2PASigningEnabledFunction · 0.85
hasEmbeddedManifestFunction · 0.85
signC2PAFunction · 0.85
hasMethod · 0.80
warnMethod · 0.80
updateMethod · 0.80
walkFunction · 0.70

Tested by

no test coverage detected