The verification model

What "verified" means

After every correction CECO renders the page before and after at its working resolution and compares every pixel. A correction is verified when:

On a scan stored as a JPEG, the declared region is whole compression blocks of the stored image, 8 by 8 of its pixels or 16 by 16 where its colour is subsampled, because a correction replaces whole blocks rather than leaving one half changed. The manifest says so for each correction.

It is a statement about the image, made by the service about its own output. It is not a statement that the corrected text is true or that anybody was entitled to change it.

Reading a verification

GET /v1/documents/{document_id}/verification describes the document as it now stands:

The export gate compares the verification's hash of the file with the hash of the file being released. A document that changed after it was verified cannot be downloaded until it is verified again (verification_hash_mismatch).

The quality score

passed says that a correction changed nothing outside its region. quality says how good the correction itself is, in words a person can act on. Each correction in GET /v1/documents/{document_id}/corrections carries its own, and the answer to POST /v1/documents/{document_id}/edits and GET /v1/documents/{document_id}/verification carry the score of the correction they verified.

It has four parts, components, each with a level, a code and a plain sentence:

Each part is good, fair, weak or unknown, and the check can also be not_applicable. The score, level, is the lowest of the parts that apply, and headline says it in one sentence. Drawn letters are at most fair, however closely they match: they are not the document's own print. A part the record does not cover reads not_recorded and is unknown, and then so is the score: a correction to a scan made before the service attacked its own work has no check to report, and is never scored as good. Read a code you do not know as unknown.

advice says what would make a correction to this page better, and only where something measured on the page supports it: a scan at 300 dots per inch, which could let a correction be written into the scan rather than laid over it (scan_300), a greyscale scan instead of black and white (greyscale_scan), or why the check could not run (not_checked_ followed by the reason). It is empty when nothing measured supports any.

The score is worked out each time it is read, from what was recorded when the correction was made, and stored nowhere: the same record always gives the same score, and version says which version of the scoring gave it. It is null for a correction whose record holds no measurements and for a document made by a page operation, a compression, marks or OCR. Null never means good. Like self_attack, it never changes passed.

The manifest

GET /v1/documents/{document_id}/manifest returns the provenance record embedded in the corrected file: every correction, where it was made and how, as written by the engine. It is returned exactly as written.

The record

Every upload, correction, undo, export and download is written to an append-only record in which each entry carries the hash of the one before. GET /v1/audit/verify-chain recomputes the chain and says where it breaks, if anywhere. GET /v1/audit/export (Business) returns the whole record as a file with that verdict inside it.

Certificates

POST /v1/documents/{document_id}/certificate issues a signed verification certificate: both SHA-256 hashes of the document, every correction and its measurement, and the record's head when it was issued, signed with Ed25519. Anybody can check one, without a key:

A certificate is not a notarisation, a legal attestation or an invoice.

The same, for people

How a scanned PDF is corrected and checked describes this model for somebody using the interface rather than a program: how a correction is made, what it is compared against, and what is refused.

Last updated