Bates stamping batch — page-bottom numbers across an entire production

Pick a source + prefix + start. Every PDF in the source gets sequential Bates numbers stamped on every page; results land as new immutable versions.

Updated 2026-04-30

/bates-stamp is the production-ready Bates labeling surface. Pair it with /privilege-log: the privilege log uses the same prefix + start convention, so log rows and stamped PDFs match exactly.

**The flow:**

1. Pin the docs you're producing into a collection (matter, custom folder, "Production set 1") OR build a saved search that returns those docs. 2. Open /bates-stamp. Pick the source. Set a Bates prefix (default "KOD") and a starting number. 3. Click **Stamp Bates batch**. Confirm. Kodori loads each PDF in alphabetical-display-name order and: - Computes the doc's Bates range `[beg, beg + pages - 1]` - Stamps the bottom-right of every page with the sequential Bates number via pdf-lib (with a thin 0.85-opacity white pad behind the text so the number stays legible over dark page footers) - Saves the result as a new document version pointing to the original via previousHash - Advances the global counter for the next doc 4. The result table shows BEG / END / pages / doc-link per stamped doc and the final cursor position so you know where to start the next batch.

**Convention.** Each DOCUMENT gets a contiguous Bates range. Each PAGE inside the doc gets one number starting at the doc's BEG. /privilege-log v2 shows each doc's BEG number on the log row; this surface produces PDFs with the full BEG-END range stamped on. Use the same prefix + start across both and the log + the production reconcile exactly.

**Permissions + filtering.** Permission-trimmed before stamping — docs you can't read drop out silently. Non-PDFs drop out silently (e.g. a Word file in the source). The skipped count surfaces above the result table.

**Caps + costs.** v1 caps at 200 docs per batch — productions larger than that are typically multi-volume anyway. Each PDF round-trip is one R2 GET + one pdf-lib parse + one R2 PUT. A 50-doc batch with average 10 pages each runs in ~30-60 seconds.

**Audit trail.** Each stamp fires document.version-committed with reason="bates-stamped" plus batesPrefix / batesBeg / batesEnd / pageCount in the payload. Webhook subscribers + the /audit log surface stamped versions naturally. Future "produced to whom?" report joins these events with recipient metadata.

**Coming next:** custom stamp positioning (top-left, top-right, etc.); custom stamp formatting (with date, with confidentiality marker, with custom font); per-doc Bates ranges (skip docs that already have Bates); produce-to-recipient workflow that ties stamped versions to a specific outbound production.