Skip to content
July 31, 20264 min read

Detection Returns Four States, and One of Them Proves Nothing

The Code the Commission found adequate on 8 July puts you on the read side: a detector strangers may call, a resolver that has to answer them, and a retention window the Code leaves you to set

Ihor K

CEO

EU AI Act
content detection
watermarking
provenance

Provenance plans get written from the write side: mark the output, sign the manifest, close the ticket. The question that actually arrives comes from the other direction — here is a stored file, tell me what made it. A detector that answers yes or no is under-reporting what it found.

The question arrives late and from outside the building: a platform's review queue, a rights holder's letter, a fact-checker holding a screenshot. On 8 July 2026 the Commission published its adequacy opinion on the Code of Practice on Transparency of AI-generated Content, finding that the Code adequately covers Article 50(2), (4) and (5) and facilitates their implementation; the AI Board endorsed that assessment the following day. From the write side that reads as a duty to mark. From the read side it is a heavier one: signatories publish a detection solution, ordinarily free of charge, and keep it free and unrestricted for regulators, media, fact-checkers, researchers and civil society. Your detector stops being an internal tool on the day you sign. Whatever it returns is a published answer, and the number of distinct answers it has to be able to return is larger than most detector designs allow for.

Signed metadata and an imperceptible watermark fail in opposite directions, and the Code asks most content types to carry both. Size explains the split. A raw ECDSA P-256 signature is two 256-bit integers — 64 bytes — before a key or a certificate joins it, and a C2PA manifest carries a great deal more than the signature: assertions, hashes, a certificate chain. A mark that has to survive a resize, a re-encode and a screenshot has nowhere to live but the signal itself, spread redundantly through it, and the channel that survives those transforms sits orders of magnitude below that budget. So metadata holds the full record and dies on the first re-upload that strips it, while the watermark survives holding an identifier. Two marks, read independently, give four results: both present and agreeing, metadata only, watermark only, neither.

An identifier is a pointer, and a pointer needs something to point at. C2PA's Soft Binding API says so in the plainest terms available: the watermark value is a key, and a resolution endpoint hands back the manifest store that key belongs to. The day you shipped watermarking you shipped that endpoint, and the callers are not your services — the entire point of the regime is that people who did not generate the content can check it themselves. The failure mode sits right there, and it is worse than it looks. The intuition that a 503 from the resolver degrades the answer to metadata only is wrong: a watermark that cannot be resolved is indistinguishable from one that was never applied, so what the detector records is neither, the state that proves nothing. The API spec lists a 500 for service failure and sets no bound on how often it may be returned. That bound is yours to write, and it belongs on the same page as the uptime targets you already report.

Retention arrives dressed as routine. Generation logs live exactly as long as a bucket lifecycle rule or a SIEM contract says they do, and both are written in months, because both were written for incident response. The asset those logs describe can sit on a customer's site for years after the row is gone. The watermark still decodes cleanly, it resolves to nothing, and at the API a clean decode of a dead pointer looks exactly like a file that was stripped. The Code sets what you must mark and what you must publish; what it does not set is how long a manifest has to stay resolvable. So the window is yours, and the only defensible way to size it is the lifetime of the asset rather than the lifetime of a log — which means someone has to hold that number, and it will not be the team that wrote the lifecycle rule.

The fourth state is where the engineering runs out. Neither can mean a transcode dropped the mark, or that someone stripped it deliberately, or that nothing ever marked the file, and at read time those are the same bytes. No work on your side separates them, because the difference lives in a history the file no longer carries. So return the state rather than a verdict: four values in the API contract, unknown spelled out as a first-class result, carrying the timestamp of the resolver lookup that produced it. Then look at the date the Code sets. By 2 February 2027 detection has to be interoperable — a query about a file reaches whichever provider can answer it, without the asker running every detector in turn. The requirement runs both ways: your resolver answers queries from other people's tools, and theirs answer yours. Every fourth state any of them returns is a file the ecosystem has collectively agreed it cannot account for. As of July 2026 that count is yours alone to explain, each provider accounting for it in its own terms. The interoperability deadline of 2 February 2027 is what puts the same count in front of everyone else's tools.