Story 2485: page billing ledger guards

Why this exists

A retry, re-read, duplicate upload, or virtual family child must never turn one physical page into two charges. The ledger is the immutable receipt book: one charge per physical Original and verb, with corrections written as linked credits or reversals instead of edits.

The guarded path

future full-package completion signal (Story 2508)
  → successful + human initiated? otherwise no row
  → resolve document → physical Original receipt
  → INSERT charge ON CONFLICT DO NOTHING
  → append blank-page credit when needed

failure / machine work → no charge
retry / re-read / family child / duplicate reuse → same Original → no charge
correction → linked credit or full reversal row → original stays untouched
No emission in this Story. The service is deliberately unwired: no extraction worker, projection, route, or persistence path imports it. Story 2508 alone owns calling it after the complete INTAKE package succeeds.

What the ledger may remember

AllowedStructurally absent
Firm, opaque matter/document/Original/job IDs, INTAKE or CREATE, extraction/rendition version, exact page count, included/overage split, rate-card version, initiator, timestamps, and correction references. Document text, quotes, prompts, party names, filenames, arbitrary JSON, or any other content-bearing field.
Database-owned safety. Forced firm RLS hides other firms. The app role receives only SELECT and INSERT. A trigger rejects UPDATE/DELETE, a constraint rejects machine charges, unique keys collapse retries and shared-Original attempts, and serialized correction guards prevent over-crediting.

Proof

Recall

One physical Original earns at most one immutable charge per billing verb; every retry collapses, every correction appends, and no document content can enter the receipt book.