Appearance
ADR-0074: A document records its page count where one can be read, the count is nullable, and withdrawing a verification stays refused
Status: Accepted — supersedes ADR-0059 Date: 2026-09-20
Decisions
D-151 Sds.pageCount is nullable, and the verification gate has two forms
Where a page count can be read it is recorded at admission, from pdf.js's numPages. Where none can be read it is null, and admission is not refused for the lack of it.
The gate follows the count:
- count known — a verified page must exist for every page from 1 to the count. This is what catches a document missing its trailing pages.
- count null — verified page numbers must run contiguously from 1. This catches a missing first page and any interior gap, and cannot catch a missing trailing page. That residue is named, not closed.
D-152 Withdrawing a verification is refused
@@unique([sdsId, pageNumber]) spans soft-deleted rows, so a soft-deleted verification keeps its page's key and that page can never be verified again. This is a ruling and not an artefact of the schema, and it is stated once here because ADR-0059 stated it four times and denied it once.
What is not ruled is whether a withdrawal capability should ever exist. Nobody has needed one. If one is ever wanted it is an ADR first and a migration second.
What this supersedes
ADR-0059 is superseded, not amended, on four counts. Three are its own text and one is a ruling made after it.
- The nullable count. ADR-0059's "may not be re-decided" section says "do not make the page count nullable". The owner ruled nullable, after that ADR was written, on the ground that the upload policy admits a photograph of a binder page — and a one-page image has no
numPages. Both repositories ship nullable. ADR-0059 never mentions the image-admission case at all, so its "What is closed off" section closes off the case that actually occurs. - It contradicts itself on withdrawal. Its Context says the question "is deliberately not answered here"; its Decisions, its Decision paragraph and its Rejected options all say the refusal is the ruling. A reader cannot act on both.
- It miscites ADR-0029. It says withdrawal "bears on ADR-0029". ADR-0029 rules that the prototype has no accounts, no sync and no favourites, and says nothing about whether a named person's judgement can be taken back. The claim is dropped rather than re-homed: the weight behind the refusal is that Curation is where every irreversible judgement in this product happens, which
CONTEXT.mdalready says. - It miscounts ADR-0052. Its amendment section says ADR-0052 asked for a ruling in "both sentences"; ADR-0052 asks once, in one sentence covering both holes — "Both need a ruling on re-verification."
What ADR-0059 got right and this ADR keeps: the count comes from pdf.js in the curator's browser (D-111), where it is already in hand; the every-page check is what closes the trailing-page hole ADR-0052 named; and the unique constraint is not narrowed.
The amendment ADR-0059 recorded against ADR-0052 is carried forward by this ADR. ADR-0052's Consequences named two holes and said both needed a ruling on re-verification; this ADR is that ruling, in ADR-0059's place. ADR-0052 stands and stays unedited.
Context
The page count was introduced to close a hole ADR-0052 named: a whole-document check that knows only which pages it has seen cannot tell a complete document from one missing its tail.
What ADR-0059 did not know is what the upload policy admits. A stored copy is not always a PDF — a curator photographing a page of a binder produces a single image, and an image has no page count to read. Writing "do not make the page count nullable" made the common floor case unadmittable, which is why the owner ruled the other way within the day.
The two-form gate is the consequence. A count is evidence when it exists, and its absence is a fact about the document rather than a defect in it. The contiguity rule remains the best available check when there is no count, with its trailing-page blind spot intact and named — the same residue ADR-0052 declared, surviving exactly where no count can be read.
Decision
A document records its page count where one can be read and carries null where none can. The verification gate checks every page against a known count, and contiguity from 1 against a null one. Withdrawing a verification is refused.
Rejected options
- Requiring a page count, and refusing admission without one — rejected by the owner on 2026-09-20. This was ADR-0059's position. It loses because the upload policy admits a photograph of a binder page, which has no
numPages: the rule would refuse the documents curation actually meets. - Narrowing
@@unique([sdsId, pageNumber])to live rows — rejected. It settles by migration a question nobody has needed answered, and the constraint is what makes the refusal hold. - Treating a null count as a known zero, or as an error — rejected. Zero would make every image document fail the every-page check vacuously or absolutely depending on the comparison, and an error is the refused-admission option under another name.
- Keeping the contiguity check as the only rule — rejected, as ADR-0059 rejected it, and for its reason: a run from 1 with nothing after it is indistinguishable from a complete document to a gate that never learned how long the document is. It survives only where no count exists.
This ruling may not be re-decided
If a change contradicts this ADR: stop and raise it. Do not implement over it.
Specifically: do not make the page count required, do not refuse an admission for the lack of one, do not run the contiguity rule where a count is known, do not narrow the unique constraint, and do not add a withdrawal path without an ADR.
Consequences
What becomes true. A PDF missing its trailing pages fails the gate. A photographed page is admissible. The ruling and both repositories agree, and the withdrawal position is stated once.
What this costs. Two gate forms rather than one, and the weaker form is the one that runs on the documents least likely to have been checked another way. A document admitted before the count existed has none and is checked by contiguity until it is re-admitted.
What is closed off. A required page count, a narrowed unique constraint, and withdrawal.
Coverage
| Upstream | Landed in | Evidence | Note |
|---|---|---|---|
| D-119 | D-151, D-152 | no span exists for a document with an unverified page; both gate forms are that rule made checkable, and the refusal is what keeps a verification final | ADR-0052; this ADR supplies the re-verification ruling ADR-0052 asked for |
| D-111 | D-151 | the count is pdf.js's numPages, already rendered in the curator's browser, so no new parse is introduced and none is available for an image | ADR-0048 |
| D-112 | D-151 | the upload policy admits the image content types a photographed binder page arrives as, which is the case the nullable count exists for | ADR-0048 |