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:
- the pixels that changed all lie inside the region the correction declared, so
outside_pixelsis0on every page; and - every guard passed (the text is where it was measured to be, the edit kept to its own line, and so on).
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:
passed: whether it may be released;- per page,
changed_pixels,outside_pixels(must be0) and the box that changed; - each guard, with
passedand a detail line; self_attack: what the service's own forensic detectors found when they attacked the correction before it was handed over:clean, aweaknesswith the detector that found it and how strongly, ornot_checkedwith the reason, such as a kind of page the check has not been measured on. A weakness is stated, not hidden, and it never changespassed. A correction the detectors find far more readily than the service's usual corrections on that kind of page is not delivered at all (self_attack_refused).
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:
letters, where the new letters came from: typed into the document's own text in its own font (typed), the same with its line changing length, so any words after it on that line moved (typed_shifted), the page's own marks moved (moved), drawn in a matching typeface and measured against the letters around them (fitted) or drawn without that measure (drawn), whole lines drawn again, the words not changed included (redrawn), nothing drawn because words were only taken out (none_drawn), or the paragraph set again (set_again);paper, what lies under them:untouched(no paper filled in), the page's own paper copied from a blank part of the page (continued),reconstructedfrom the page around it, or oneflattone;file, how the change was written into the file: into the scan's own compressed image (own_compression), laid over the scan as a new image (overlay), or as text with no image added (text_only);check, what the service's own forensic detectors found when they attacked the correction (clean,weaknessornot_checked, as inself_attack), with thedetectorthat showed a weakness most or thereasonthe check did not run, andwhereon the page they looked: aboxin pixels at itsdpi, rounded outward, given only when the page's image covers the whole page and its size and resolution were recorded.cleanandweaknesscompare the correction with the same kind of change already on the paper when that kind of page was scanned, never with the page alone. The check examines images of the page, so it does not apply to a change made in the document's text: that part isnot_applicable.
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:
GET /v1/certificates/{id}returns whether it is valid, its hashes and its date;POST /v1/certificates/verifychecks a certificate file's exact bytes;- the public key is at
/.well-known/ceco-certificate-key, so the signature can be checked without CECO at all.
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