Cameras, phones and AI image tools are shipping C2PA Content Credentials now, and almost every fediverse server throws them away the moment a photo gets resized. By the time a post federates, nobody downstream can tell a camera shot from a generated image.
This FEP adds two optional properties to attachments:
- digitalSourceType, an IPTC Digital Source Type URI, so receivers can label AI generated and AI modified media without parsing C2PA themselves
- contentCredentials, a small summary of what the origin server found when it validated the upload (validationState, signer, claimGenerator)
It also covers how a server can sign its own resized copy, with the original as the parent ingredient, so the provenance chain survives for anyone who wants to verify the file themselves.
Privacy was a big part of this. Manifests can carry EXIF with GPS, identity assertions and pre-crop thumbnails. The FEP says not to republish any of that, and to redact it from the parent manifest before re-embedding.
Thanks for writing this up. Getting provenance to survive federation is worth doing. Some C2PA-specific notes on the discussion so far, then a review of the draft itself.
On the thread
parentOfingredient binds to the parent’s manifest (hashes of itsactiveManifestandclaimSignature), not to the parent’s pixels. A signed derivative is therefore the server attesting “this file came from that one” under its own certificate. What it adds over a plain summary is accountability: the claim is signed and attributable to a named signer, and the parent’s manifest and signature can still be checked independently. Receivers should present it as “signed by server name”, not as the camera’s credential..c2pafile, advertised withLink: <…>; rel="c2pa-manifest"(§15.5.3.2). Receivers could then check the signature, signer and editing history themselves. They couldn’t confirm the manifest binds to the displayed pixels, so the asset won’t be a Valid asset, but they would no longer depend on the server’svalidationState. The catch: the sidecar carries the same personal metadata, so the redaction rules still apply, and redacting means re-signing.Trustedproduces a positive claim. It may be worth requiring receivers to show “reported by origin” differently from “verified locally”.exif:GPS*fields are among those allowed inc2pa.metadata, so offering this as an author opt-in seems reasonable. Once the location is copied into an ActivityStreamslocation, though, it is no longer signed, so it should be presented as author-provided.Updatethat swaps in a redacted derivative is best-effort only, and I agree with @mczachurski that the FEP should say so.On the draft
I read it against the C2PA 2.4 specification it cites, and against the current 2.5 working draft. The section references (§6.8, §14.3) are correct, but a few things don’t line up with C2PA, and one rule produces the wrong label. Section numbers below refer to C2PA 2.4.
digitalSourceType
1. Rule 1 labels composites as fully AI-generated. Rule 1 looks for
c2pa.created+trainedAlgorithmicMediaanywhere in the ingredient chain. Take a camera photo with an AI-generated element placed into it (c2pa.placed,componentOfingredient). That element’s own manifest hasc2pa.created+trainedAlgorithmicMedia, so Rule 1 fires and the photo is labelled AI-generated. Rule 2 would have given the correctcompositeWithTrainedAlgorithmicMedia. A manifest has at most onec2pa.created/c2pa.opened(§18.15). So Rules 1 and 3 should follow only theparentOfchain from the active manifest down to its rootc2pa.created.componentOfandinputToingredients should feed only Rule 2. Ingredients removed withc2pa.deletedshould probably be skipped.2. Rule 3 can produce values that aren’t IPTC terms. C2PA allows its own values alongside IPTC ones:
http://c2pa.org/digitalsourcetype/emptyandhttp://c2pa.org/digitalsourcetype/trainedAlgorithmicData(§18.15.4.5).emptyis required for anything started from a blank canvas or template, so Rule 3 will often return it. The FEP should either allow these values or say to leave the property out.3. Ingredients without a manifest can carry their own
digitalSourceType. When an ingredient has no active manifest, the ingredient assertion may have adigitalSourceTypefield (§18.16.11). The rules only look at actions, so they miss these.4. Please define “AI source type”. At minimum, list
trainedAlgorithmicMedia,compositeWithTrainedAlgorithmicMedia,compositeSyntheticand C2PA’strainedAlgorithmicData. Also say whetheralgorithmicMediaandalgorithmicallyEnhancedcount.5. Only the AI label is protected. The FEP keeps receivers from dropping an AI label, but says nothing about how much to trust
digitalCapture. “This is a real photo” is the label people have a reason to fake. I’d suggest receivers SHOULD NOT present a non-AI source type as verified unless the publisher reportsValidorTrusted.contentCredentials
6. The
validationStatevalues don’t match C2PA. §14.3 defines three manifest states: Well-Formed, Valid and Trusted. There is no “Invalid”. Well-Formed (structurally fine, but the signature isn’t valid, for example because the certificate expired or was revoked) is missing, and it’s a common result in practice. C2PA also separates manifest state from asset state (§14.3.3): a manifest can be Valid while the file’s content hash no longer matches. I’d suggest the three C2PA terms plus an explicit “no valid manifest” value, or carrying the C2PA status codes.7.
signershould come from the certificate subject, not the issuer. The issuer is the certificate authority, so as written most attachments would show the CA’s name rather than “Example Labs” (§14.2).8.
claimGeneratorsource field. v2 claims useclaim_generator_info, a map withnameandversion(§10.2.3). v1 claims use aclaim_generatorstring. Worth saying which field to read for each.9. The summary describes a different file from
url. (This is the same gap @mczachurski describes.)contentCredentialsdescribes the original upload, buturlserves the re-encoded copy. Unless that copy is signed, a receiver can’t check the claim. Two possible fixes: include the original active manifest’s label (its URN) so receivers can match things up, and mention the sidecar/Linkoption described above.Signed derivatives
10. Use
c2pa.transcodedfor server resizing, notc2pa.resized.c2pa.transcodedexplicitly covers resolution scaling and is a non-editorial transformation.c2pa.resizedisn’t classed as non-editorial in 2.4, and the 2.5 draft classes it as perceptible. An actions list containing onlyc2pa.published,c2pa.transcodedandc2pa.repackagedtells consumers that nothing editorial changed (§18.15), which is exactly what a federating server wants to say.c2pa.resized.proportional(non-editorial) is another option.11. Spell out the manifest structure. The first action needs to be
c2pa.opened, referencing ac2pa.ingredient.v3assertion withrelationship: parentOf(§18.16.3). It would also help to say:12. The redaction list.
stds.exifhas been deprecated since 2.0. It still shows up in older manifests, so keep it, but it isn’t the main risk.c2pa.thumbnail.claim.*/c2pa.thumbnail.ingredient.*) is the biggest leak. In the “then cropped” example, it would show the uncropped original.*.metadataassertions (any namespace is allowed), identity assertions, andstds.schema-org.CreativeWork(author).redacted_assertions, and adding ac2pa.redactedaction is strongly recommended.c2pa.actionscan never be redacted, so the provenance history always survives.Minor
contentCredentialsunless it validated the manifest itself.”I’m happy to help with wording on any of these.