Model Receipt Notes

Notes on proving which image model actually ran

A PNG corner mark with no canvas and no WASM

Free tiers that promise "a small corner mark" usually do it with a CSS overlay, which is two clicks from being gone, or with an image library, which needs a runtime that has one. In an edge worker you have neither. No canvas, no sharp, no native binding.

What you do have is CompressionStream('deflate') and its inverse. That turns out to be the only hard part of a PNG.

The format, in the parts that matter

A PNG is a signature followed by typed chunks. Three of them matter here: IHDR carries width, height, bit depth, colour type and interlace; IDAT carries zlib-compressed scanlines; IEND ends the file. Each chunk is length, type, data, CRC32.

Each scanline inside IDAT is prefixed with a filter byte. To composite pixels you inflate, undo the filters, write your pixels, re-apply filter zero, deflate, and rebuild the chunk with a fresh CRC. That is the whole job — bookkeeping, not imaging.

The rule that keeps it safe

Never re-encode an image you do not fully understand. Anything that is not 8-bit RGB or RGBA comes back unchanged and the caller ships the original:

if (!isPng(input)) return input;
if (depth !== 8 || interlace !== 0) return input;
if (colorType !== RGB && colorType !== RGBA) return input;

A missing mark is cheap. A corrupted download is not, and silently mangling somebody's picture to enforce a badge is the worst trade available.

The chunk you must not drop

An encoder that rebuilds a file from IHDR plus pixels throws away every ancillary chunk. Modern image models embed C2PA provenance in those. If your own FAQ tells readers the provenance metadata is there and cannot be stripped, an encoder that strips it makes you a liar in a way nobody will notice for months.

Copy through every chunk you did not write.

The trap on the calling side

This is the part that actually bit us. The mark only applies to PNG — by design, per the rule above. The decision to apply it and the decision to force PNG output were two adjacent lines gated on two different values. A run that was supposed to be marked, but was allowed to request WebP, came back clean and looked like a success.

Nothing errored. Nothing logged. The file was simply unmarked.

If you build this, make the mark and the container come from one value, and write the test that reads your own source to check they still do. A behavioural test on whichever path is currently the default will pass on the morning the default changes.

The tier this runs on, and exactly what the mark does and does not mean, is written up at gptimage25.top/free.

More notes