Shipping AI Content Provenance That Actually Survives Production (Post Article 50)
The EU AI Act's Article 50 transparency rules went enforceable on August 2, 2026. If you ship a generative AI feature that touches EU users, you now owe the regulator a machine readable marking on your output. The obvious shortcut, drop a C2PA manifest and call it done, does not survive contact with production. Here is what actually works, with the code to make it real. The Two Layer Reality Article 50(2) requires effective, interoperable, robust, and reliable marking. The EU Code of Practice interprets that as at least two layers: signed metadata (C2PA) plus imperceptible watermarking (SynthID or equivalent). Fingerprinting is optional layer three. The reason for two layers is not bureaucratic. It is a screenshot. C2PA lives in a JUMBF metadata box. X strips it on upload. CDNs strip it during optimization. Screenshots destroy it entirely. Microsoft admitted this openly in its February 2026 Media Integrity report: preventing every attack on provenance is not possible. Invisible watermarks embedded in the pixel content survive those operations but carry very little information. You need both. Generating a Signed C2PA Manifest (Node) // npm install c2pa-node import { createC2pa , ManifestBuilder } from ' c2pa-node ' ; import { readFile , writeFile } from ' node:fs/promises ' ; const c2pa = createC2pa (); async function signGeneratedImage ( inputPath , outputPath , generationMeta ) { const asset = { buffer : await readFile ( inputPath ), mimeType : ' image/jpeg ' }; const manifest = new ManifestBuilder ({ claim_generator : ' firesafe/1.0 ' , format : ' image/jpeg ' , title : ' ai-generated-image.jpg ' , assertions : [ { label : ' c2pa.actions ' , data : { actions : [{ action : ' c2pa.created ' , digitalSourceType : ' http://cv.iptc.org/newscodes/digitalsourcetype/trainedAlgorithmicMedia ' , softwareAgent : generationMeta . modelName , }], }, }, { label : ' com.firesafe.generation ' , data : { model : generationMeta . modelName , modelVersion : generationMeta . modelVer