# What $10.75 bought: 43 owned business records, five receipts, and the unit of sale no vendor offers

slug: federated-object-proof · https://miscsubjects.com/a/federated-object-proof · tags: protocol, economics, objects, canonical · updated 2026-07-29T00:35:35.160Z

On 28 July 2026 at 16:30:38, a customer of this system paid **$10.75** and received 43 property-management companies in Ottawa — each one a business record with a name, an address, a phone number and a website, owned by that customer permanently, with a receipt showing it cost $0.12 to produce.

Here is that receipt. It is a real row in a real table, and every identifier in it resolves:

| field | value |
| --- | --- |
| charge id | `ch_bf8beb55e6d349e1a419` |
| what was bought | 43 organization objects — `lead:11786` … `lead:11828` |
| price paid | **$10.75** (43 × $0.25 per organization, the price published on the capability row) |
| what it cost to produce | **$0.12** — 3 Google Places API requests at the published $40.00/1,000 SKU |
| the invocation that produced it | `inv_yxg5jmhamu`, trace `t_e13e9txt` |
| owner | `t_plumber-demo` — stamped on all 43 rows at insert |
| buyer's balance | $30.00 → $19.25, then $14.53 after four more purchases |

Four more purchases followed in the next two minutes: 6 contacts resolved ($3.00), 6 email domains verified ($0.12), 16 leads scored by a model ($1.60). One draft was refused by a quality gate and charged nothing. Total: **$15.47 charged on $0.125022 of real cost**, five receipts, every object owned by the buyer — and those totals are the ones the public receipts endpoint returns, not numbers retyped into prose.

You can check all of it right now, without a login. **[All five receipts are public](https://miscsubjects.com/api/objects/receipts?tenant=t_plumber-demo)** — capability, units, recorded cost, price, and the invocation and object ids for each. The objects those receipts bought are not public: [fetch one](https://miscsubjects.com/api/objects/lead/11822) and you get a refusal receipt naming the owner, which is what ownership looks like from outside. The customer takes everything with them through [one export request](https://miscsubjects.com/api/objects/export?tenant=t_plumber-demo) with their own token. The tables further down this page query the production database when the page loads — they are not screenshots.

**MCP standardizes how a model reaches a tool. Nothing standardizes what you own when the tool returns. That missing layer is the product.**

Everything below is evidence for that one sentence.

If you have no context for this site: it is one deployed system — a public knowledge corpus and an invocable capability directory sharing one database, one authority model and one append-only ledger, described at [the-unified-loop](/a/the-unified-loop). Three articles carry what this page stands on and does not repeat: [buy-outcomes-not-subscriptions](/a/buy-outcomes-not-subscriptions) is the database audit, run hours before this page, that measured exactly what was missing and specified the minimum proof this page executes; [object-ledger-evidence-graph-spec](/a/object-ledger-evidence-graph-spec) is the object grammar, the ledger, and the evidence graph these objects live in; [palantir-foundry-ontology-models](/a/palantir-foundry-ontology-models) is the closest incumbent architecture, surveyed. The prose rules, the decision rules and the surface rules this page was written under are public too, at [writing-law](/a/writing-law), [logic-law](/a/logic-law) and [design-law](/a/design-law) — the first publish attempt of this page was mechanically refused for not proving it had read the first one.

## Who this is for: the business paying $1,500 a month for someone else to press the buttons

A plumbing contractor in Ottawa does not want a lead-generation platform. He does not want a seat license, an onboarding call, or a dashboard he will open twice. He wants more customers, and today his only options are these:

He can hire an agency at $1,500–$5,000 a month, whose actual work is operating tools he could theoretically buy himself — a data vendor, an email platform, an ad account. He is not paying for the tools. He is paying a person to press the buttons, because the tools assume a full-time operator he does not employ.

He can buy the tools directly and become that operator. ZoomInfo will sell him access at a buyer-reported median of $31,875 a year across 1,313 verified purchases, three seats minimum, with reported contract terms requiring destruction of exported contacts at the end ([claim c13](/a/buy-outcomes-not-subscriptions)). He needs one seat and 200 contacts. The unit does not exist at his size.

Or he can do nothing, which is what almost everyone does.

Software has spent twenty years selling to the small fraction of businesses that will hire an operator. The rest — the plumber, the dentist, the two-truck landscaper — never buy the tools at all, because a tool you must learn to operate is not a product to someone whose day is already full. **The metered protocol removes the operator, not the tool.** The plumber states the result he wants in one sentence, the machine does the work, and he pays for the units delivered — $0.25 per business found, $0.50 per contact resolved, $0.02 per domain verified. No seat. No minimum. No month.

$15.47 of that arithmetic is on this page as receipts. The agency's $1,500 is not comparable to a subscription; it is comparable to the *work*, and the work now has a price per unit.

## What ran, in order, with the artifact from each step

Every step below executed against the live production system on 2026-07-28. Nothing is illustrative.

**Step 0 — a stranger becomes a customer.** One route, added as part of this work:

```
POST /api/tenants
{"tenant_id":"plumber-demo","name":"Ontario plumbing company (demonstration tenant)",
 "allow_prefixes":"LEADS","balance_usd":30}

→ 200 {"ok":true,"tenant":{"tenant_id":"t_plumber-demo","status":"active",
       "balance_usd":30,"created_at":"2026-07-28T16:29:55-07:00"},
       "funding":{"funded_usd":30,"by":"owner:federated-object-proof"}}
```

A capability token was then minted bound to that tenant — `cap_48d9ef30a3a6e5a8`, scope `pfx:LEADS`. It can invoke lead capabilities, read only its own receipts, and nothing else. Every request below carries that token and no other authority.

**Step 1 — the machine reads the request.** The build's own planning model was unavailable: its provider (xAI) had hit a spending limit, and the failed attempt is itself a permanent ledger row, `inv_0dq1sobaua`, recording the provider error. A different vendor's model interpreted the request instead, which is the whole point of treating the model as a replaceable operator rather than the system:

[[embed:source:m5]]

Two questions, both necessary: what kind of customer, and what budget. No qualifying call. No discovery session. The answers were "property management companies" and the funded $30.00.

**Step 2 — the price comes off the row, not out of a negotiation.** Every capability carries its price and its unit in the same table that documents and executes it. This is the live query, and the table below it is that query rendered at page load:

```sql
SELECT key, price_usd, meter_unit FROM directory WHERE price_usd > 0;
```

[[object:actions]]

**Step 3 — the purchase.** The tenant's token invoked the first rung:

```
GET /api/dispatch?invoke=LEADS_DISCOVER_PLACES
    &body=property management company|Ottawa|40
    &share=<tenant token>

→ invocation inv_yxg5jmhamu · trace t_e13e9txt
  {"inserted_new": 43, "units": 43, "meter_unit": "organization",
   "api_requests": 3, "cost_usd": 0.12,
   "cost_basis": "Google Places Text Search Enterprise + Atmosphere — $40.00/1,000 requests",
   "tenant_id": "t_plumber-demo",
   "object_ids": ["lead:11786","lead:11787","lead:11788", … 43 total],
   "charge": {"id":"ch_bf8beb55e6d349e1a419","units":43,"price_usd":10.75,"cost_usd":0.12}}
```

The $0.12 is not an estimate. It is three requests at Google's published SKU price, verified against the live price sheet the same day:

[[embed:source:s1]]

**Step 4 — the second capability reads the first one's objects.** No CSV. No export. No re-entry. Enrichment selected the objects the discovery step had just created and returned both what it read and what it changed:

```
GET /api/dispatch?invoke=LEADS_ENRICH_BATCH&body=8&share=<tenant token>
→ inv_itzk33ejzz
  read_object_ids: lead:11819 … lead:11828     ← created by inv_yxg5jmhamu
  object_ids:      lead:11822 lead:11823 lead:11824 lead:11825 lead:11826 lead:11828
  units: 6 · charge ch_71c7ba3dd9724032b6cc · $3.00
```

Two of the eight sites yielded no address and were not charged for. The reuse is measurable rather than asserted:

```sql
SELECT COUNT(*) FROM charges
WHERE tenant_id='t_plumber-demo' AND object_refs LIKE '%"lead:11822"%';
-- 3
```

One business, bought once, used by three separate paid operations — found, then enriched, then verified — with no second purchase of the business itself. Each later charge priced only its own new work.

**Step 5 — verification, then judgment.** MX verification checked 6 email domains against a free public resolver and charged $0.12 for the check (`inv_udch4ldam8`). Two model passes scored 16 leads for $1.60 total against $0.005022 of real model cost (`inv_t0hj0gnaqr`, `inv_adqd0upv3p`).

**Step 6 — the gate that refused and charged nothing.** Drafting was invoked on a lead before it qualified:

```
GET /api/dispatch?invoke=LEADS_DRAFT_AI&body=11822&share=<tenant token>
→ inv_55crgyc6kc · charge: none
  {"blocked": true, "error": "icp_threshold_not_met", "score": 5, "minimum": 65,
   "note": "Nothing drafted. Only verified high-fit leads enter copy review."}
```

No unit delivered, no charge. That is the metered promise under refusal, which is the only condition in which it means anything.

**Step 7 — what the customer holds now.** 44 objects (43 bought plus one synthetic demonstration record), 6 verified contacts, 5 receipts, and $14.53 of unspent balance. The next offer is computed from that state, not from a sales sequence: *you hold 6 verified contacts; drafts are $2.00 each on the row.*

![The demonstrated purchase loop, with the real identifiers from this page's own demonstration](/assets/figures/federated-object-loop.svg)

*Figure 1 — every identifier in these boxes is real and queryable. The unit of sale is the object in the middle, not the capability that made it or the model that operated it.*

## The margin, done out loud, with the real numbers

The receipts above make the pricing argument checkable rather than rhetorical. This table uses the actual charges from this page's demonstration in the third column, and published vendor figures in the first two:

| | Agency / contractor | Subscription stack | This demonstration |
| --- | --- | --- | --- |
| What you pay to get started | $1,500–$5,000 / month retainer | $31,875 / year median contract, 3-seat minimum ([c13](/a/buy-outcomes-not-subscriptions)) | $0.00 — you pay per unit |
| What 43 qualified businesses cost | inside the retainer, not itemised | inside the contract, not itemised | **$10.75**, itemised, receipt `ch_bf8beb55e6d349e1a419` |
| What 6 verified contacts cost | inside the retainer | inside the contract | **$3.12** (enrichment $3.00 + verification $0.12) |
| Recorded cost to produce all of it | not disclosed | not disclosed | **$0.125022**, on the ledger, per invocation |
| Who operates it | the agency | you, or the operator you hire | the protocol |
| What you hold if you stop | whatever the contract said | access ends; exported contacts reportedly destroyed | the objects, exported in full, forever |
| Marginal cost of one more unit | renegotiation | credit burn, then overage | the published unit price |

The pricing rule, stated so it can be argued with: **substantially below the customer's real alternative, substantially above fully loaded marginal delivery cost** — where fully loaded means the APIs, the data acquisition, the deliverability infrastructure, the failures, the verification, the maintenance, the model judgment, and the amortised cost of having built the capability at all. Compute-plus-markup is banned as a pricing basis, and the row above shows why: $0.125022 of provider cost against $15.47 of price is not a markup on tokens, it is the price of work that would otherwise cost a month of somebody's salary. The customer's comparison is the agency retainer, not the DNS bill.

## The strongest objection, published unedited, and what it forced

A hostile reviewer was asked to name the single weakest claim on this page and destroy it. Its answer was correct enough to change the system before publication:

[[embed:source:m7]]

The attack is right on the first half and it should be read twice: *possession that requires the custodian's permission layer to be online, honest, and solvent is custody, not property.* An object you can only reach through the seller's gate is a lock-in token denominated in your own data, and the 403 refusal this article was proud of proves the gate exists rather than proving ownership.

So the claim was not defended in prose. The system was changed. A tenant can now take everything and leave, with their own token, in one request:

```
GET /api/objects/export?tenant=t_plumber-demo&share=<tenant token>
→ 200 · 29,128 bytes
  {"export_of":"t_plumber-demo","counts":{"objects":44,"charges":5},
   "tenant":{"balance_usd":14.53,"status":"active"},
   "license":"These objects are the exporting tenant's property. This file is complete,
              unencumbered, and carries the provenance for every row: nothing here requires
              this system to remain online, solvent, or willing.",
   "objects":[…44 complete records including email and phone…],
   "charges":[…5 receipts…]}
```

Without the tenant's token the same URL returns `403 export_requires_owning_tenant`. The export is free, complete, and includes the receipts, because provenance that cannot leave with the object is provenance that only serves the seller.

What the export does **not** fix, and the reviewer is still correct about: the objects were produced by this system's contracts with Google and its own runners, and nothing outside this system currently accepts a miscsubjects object as a typed input. Portability today means the buyer holds a complete file, not that a competitor's capability can consume it natively. Federation between providers is a claim about a future standard, not a demonstrated fact, and it is registered as an open gap below rather than smuggled into the demonstration.

The second half of the attack is simply true and was already on this page: the global queue billed this tenant for 8 rows it did not own. The reviewer found it because it was disclosed, which is the argument for disclosing it.

## The object, at three levels of magnification

The word for what was sold is **object**: one unit of completed work with a stable identity, an owner, a recorded production cost, a price, a verification state and a receipt. Here is one, live, at every zoom the system holds it at.

**Zoom 1 — the row.** What a list vendor sells you, frozen at export. These are real rows from the customer's 43, read from the production table at page load:

[[object:rows:tenant:t_plumber-demo]]

**Zoom 2 — the card.** The same object opened: identity, contact state, verification, qualification, and then the block no list vendor has ever shown a customer — which capability created it, from what source, on what date, under which owner, and every charge that ever referenced it.

The public demonstration card is a synthetic record, labelled as such on its face, because real customers' contact details belong inside the boundary they paid for. Its machine actions and verification states are real:

[[object:card:lead:11829]]

**Two real objects from the purchase.** Same renderer, same page load, real Ottawa businesses. Their provenance is public; their contact fields are not, because those belong to the tenant that paid for them:

[[object:card:lead:11822]]

[[object:card:lead:11824]]

**The boundary, demonstrated rather than promised.** A person rendered as an object is exactly the dual-use mechanism the object grammar names — the same card that serves a buyer serves a stalker if the boundary is missing ([dual-use claims c25, c26, c29, c34](/a/object-ledger-evidence-graph-spec)). So the boundary refuses in public, and the refusal is itself a recorded event rather than a blank page:

```
GET https://miscsubjects.com/api/objects/lead/11822          (no credential)
HTTP 403
{"refused": true, "reason": "cross_tenant_read", "object": "lead:11822",
 "owner_tenant": "t_plumber-demo", "ts": "2026-07-28T16:33:22-07:00",
 "note": "This object belongs to t_plumber-demo. It renders only inside its owning tenant's
          boundary — the same rule the invocation read path enforces. This refusal is
          recorded on the invocation ledger."}
```

**Zoom 3 — the action surface.** The object's future: every capability that can be bought against it, with its price, computed from the directory at page load rather than curated by hand. That surface is the table in Step 2 above; on a customer's own card it renders as buttons.

Read the three zooms against the vendors: ZoomInfo sells zoom 1 and contractually destroys it at exit. The unit here is zoom 2 with zoom 3 attached, and it walks out the door in a 29KB file when the customer wants it to.

![The loop as executed: solid boxes ran with the shown receipts; dashed boxes name the exact missing column](/assets/figures/federated-object-gaps.svg)

*Figure 2 — solid boxes ran, with invocation and charge ids. Dashed boxes are gaps this demonstration surfaced, each with its named fix. A gap drawn on the same figure as the receipts is the difference between an audit and an advertisement.*

## What was broken this morning, what the receipts retired, what is still open

This page's predecessor was an audit, published hours earlier, which proved the paid loop could not run ([buy-outcomes-not-subscriptions](/a/buy-outcomes-not-subscriptions)). The honest structure is therefore before and after, not confession:

| Defect, as measured this morning | State now |
| --- | --- |
| 99.1% of 170,317 invocations recorded `cost_usd = 0`, including every LEADS call ([c1](/a/buy-outcomes-not-subscriptions), [c2](/a/buy-outcomes-not-subscriptions)) | **Retired for the seven capabilities being sold.** They report real provider cost on return; this demonstration's discovery call recorded $0.12 and its scoring calls $0.005022. History does not rewrite: the all-time ratio is now 169,107 zero-cost of 170,576, and it will move only forward. |
| `leads` had no `tenant_id`, so no produced object could have an owner ([c3](/a/buy-outcomes-not-subscriptions)) | **Retired.** One column, stamped at insert. All 43 objects carry `t_plumber-demo`. |
| `directory` had no price column; tenants had no balance ([c4](/a/buy-outcomes-not-subscriptions)) | **Retired.** `price_usd` and `meter_unit` on eight rows; `balance_usd` on tenants; a `charges` table joining price to cost to invocation to object. |
| No route existed to create a paying customer | **Retired.** `POST /api/tenants`, used in Step 0. |
| An object could not leave the system | **Retired after the hostile pass above.** `GET /api/objects/export`, 29,128 bytes, free, complete. |
| `waste` summed to zero; nothing recorded whether work produced a result ([c15](/a/buy-outcomes-not-subscriptions)) | **Still open.** `charges.outcome` now exists and is NULL on all five rows. Until it fills from real campaign results, "the protocol learns what works" is a bet, and it is priced as one: at zero. |
| Batch queues are global, not tenant-scoped | **Still open, and it cost the customer $0.80.** The second scoring call charged this tenant for 8 leads belonging to the operator's own pipeline. The fix is one `WHERE tenant_id` clause on queue selection. The receipt is what caught it. |
| Nothing outside this system consumes these objects as typed inputs | **Still open.** Portability is proven; federation between independent providers is not. |
| Batch sending is disabled; 42 messages have gone through the owner-reviewed path | **Deliberate, and priced honestly at nothing.** Selling the send rung means selling a deliverability liability, and a protocol that sells sends must price the human review or automate the trust decision. |

Four defects were retired between the audit and this page. Three remain open with their fixes named in columns. That is the whole state, and every row of it is re-runnable.

## Why no incumbent offers this unit

The definition, now that the thing has been seen: a **federated object** is one unit of completed work, priced individually, owned permanently by the buyer, carrying provenance and a recorded production cost, and immediately usable by the next paid capability without re-entry. A **capability** is one row in a live directory — simultaneously the documentation of an operation, its executable contract, its authority boundary, and the thing the ledger names when it fires; there are 892 of them (`SELECT type, COUNT(*) FROM directory GROUP BY type` → fn 480, http 304, agent 57, flow 51). A **metered utility** prices by the unit actually delivered, with the price published where a stranger can read it before buying.

Try to buy that unit anywhere. You cannot, and a model instructed to find a counterexample could not either:

[[embed:source:m1]]

The market sells access (ZoomInfo, with a destruction clause), credits (Arcads, $110–$550 monthly tiers with credits expiring at cycle end — [c14](/a/buy-outcomes-not-subscriptions)), environments (Palantir Foundry, licensed per server core per annum with no line item for a single object — [c8](/a/buy-outcomes-not-subscriptions)), engagements (the agency retainer), and tokens (model vendors). Each of them structurally cannot offer the unit, because the unit destroys the thing they charge for: the deletion clause *is* the data vendor's moat, the expiring credit *is* the creative vendor's revenue, the environment *is* the platform vendor's contract.

And the connection standard that everyone is building on says nothing about it, by its own definition:

[[embed:source:s4]]

MCP defines how a model reaches an external system. It is silent on who owns the object that comes back, what it cost, whether it can be sold twice, and whether the buyer can take it with them. The billing shape is not exotic either — the infrastructure vendor beneath this entire build already meters exactly this way in public:

[[embed:source:s5]]

## The graph underneath, and the one property that compounds

Two things can happen through the front door. A **read** traverses objects already in the graph and changes nothing. An **invocation** performs work, and its output does not evaporate as chat — it lands as attributed objects: which capability, which model, which inputs, what cost, under whose authority ([assertion claims c15–c16](/a/object-ledger-evidence-graph-spec)).

The consequence is the only compounding claim on this page: a conventional AI product's marginal query produces a response that disappears, so the same research is re-run and re-purchased tomorrow. Here, the plumber's 43 businesses are now supply for every later capability he buys, and the reuse is the `-- 3` from Step 4, not a metaphor. **A competitor's cost of goods is flat per query; this system's declines with use, because the graph is a supply-side asset every paid query enriches.**

That claim was handed to a model with instructions to attack it, and its objection is printed here rather than survived quietly:

[[embed:source:m3]]

The objection has a real edge — the operator does write the rules — and exactly one honest boundary blunts it: the compounding is proven in the reuse direction and unproven in the outcome direction, because `charges.outcome` is empty. If later work stops reading earlier objects, the claim dies by its own falsifier.

The same discipline applies to what a model says about an object. Asked whether the demonstration business was still operating, the model refused to invent a status the record does not carry, and its answer landed as a signed assertion attached to the object rather than as anonymous fact written into its fields:

[[embed:source:m6]]

Every model card on this page carries its complete raw REST exchange — the exact request JSON including the full prompt, and the exact response JSON including token usage — under a collapsed disclosure. An edited quote proves nothing; the raw payload is the only falsifiable form of a model pass. Open one and check the quote against the response body.

## Where this sits, bounded honestly

The mainstream agent stack is arranged model-first: model → prompt → tools → app. This is arranged the other way: **governed objects → capability authority → model as replaceable operator → receipts → public and private projections.** The demonstration contains its own proof of the replaceable-operator clause: the planner's model lane died mid-loop and a different vendor's model interpreted the request; the scoring runner's primary model was unavailable and its fallback produced the scores, attributed, at recorded cost. No operation's meaning changed when the model behind it changed.

The closest relative is not an agent framework but Palantir's Foundry Ontology: both join typed objects, links, actions, functions and permissions into one governed layer, and Palantir states the same growth property claimed here — the data asset gains value as user edits accumulate ([c7](/a/buy-outcomes-not-subscriptions)). The kinship is real and the scale is not close: Palantir's published object backend supports 2,000 properties per object type and indexes tens of billions of objects for one type; this build holds thousands of articles and roughly eleven thousand leads ([c9](/a/buy-outcomes-not-subscriptions)). No claim here asserts parity.

Four divergences justify calling it a different thing: the public knowledge corpus is part of the operating system (this page is a projection of the same objects the machine operates on, which is why it can carry its own evidence); governance is machine-legible to strangers (every receipt above is publicly fetchable); the ontology models an operator, not an organisation; and the system amends the rules under which it amends itself. That fourth one is the boldest, so it was attacked too, and the attacker won:

[[embed:source:m4]]

The demanded evidence — a reproducible, persisting, unassisted amendment of the amendment mechanism — is not supplied on this page, and the claim carries that verdict on its face.

Two governance mechanisms did fire during this work, both mechanical rather than aspirational. The first publish attempt of this article was refused with `HTTP 428 write_gate`: a body write requires a token issued only to a caller that fetched the live writing law and answered questions about it correctly. The token that published this page was earned by returning the exact titles of three clauses (challenge `wg_8cb1f3f9c352e68534e96aae`, law hash `b71b5331…`). The predecessor article at this subject published as an unfilled scaffold with six empty claims — the failure that gate now refuses.

## The verdict, as a bet with its falsifier

Is this a substantive product? **Yes, on one reading and not the obvious one.**

Not as "one place to buy AI services." That is a marketplace, several exist, and 892 capabilities is breadth — the least defensible asset here, because a funded competitor can wire the same endpoints in weeks.

It is valuable as **the unit of sale no incumbent can offer without breaking their own model**, sold to the businesses that were never going to hire an operator. The machinery is not a deck: it is the directory, the token boundary, the append-only ledger, an export route, and $15.47 of real charges against a real balance, all of which a stranger can re-run from this page.

Three things must be true for the bet to pay, each checkable rather than arguable. The meter must keep reading true on every billable rung — it reads true on seven as of today. A buyer must value owning the object and not only the outcome — untested. And one complete paid loop must exist before a second vertical is exposed — it now exists, and the second vertical deliberately does not.

**The falsifier for the whole thesis:** a customer buys leads once, never invokes a second capability against those objects, and durable ownership prices at zero for them — in which case the graph is an internal efficiency and this is lead generation with better bookkeeping. That is testable at roughly five customers, and it should be tested before anything else is built.

A skeptical investor, given only these numbers and asked which claim to diligence first, named the one this page demonstrates in Step 4 and demanded exactly the artifact printed there:

[[embed:source:m2]]

[[embed:source:a1]]


## Sources

1. Google Maps Platform pricing — Places API Text Search SKUs — https://developers.google.com/maps/billing-and-pricing/pricing
2. xAI API pricing — grok-4.3 per-token rates — https://docs.x.ai/developers/pricing
3. Live production queries and runtime receipts, 2026-07-28 — https://miscsubjects.com/api/tenants
4. What is the Model Context Protocol (MCP)? — https://modelcontextprotocol.io/docs/getting-started/intro
5. Unified Billing — Cloudflare AI Gateway — https://developers.cloudflare.com/ai-gateway/features/unified-billing/
6. Kimi K3 hunts for a vendor whose unit of sale matches the definition
7. DeepSeek V4 Flash, as a skeptical investor, names the claim to diligence first
8. GLM 5.2 states the strongest case that the recursion claim is circular
9. DeepSeek V4 Pro picks the most likely overstated divergence and the evidence that would settle it
10. GLM 5.2 interprets the customer request against the priced capability list
11. GLM 5.2 examines the demonstration object and refuses to invent what the record does not carry
12. Kimi K3, instructed to destroy the weakest claim, destroys it
13. Authorship pass — drafted, demonstrated and published, disclosed


---

# The object ledger: one grammar for every record, a signed receipt for every look

slug: object-ledger-evidence-graph-spec · https://miscsubjects.com/a/object-ledger-evidence-graph-spec · tags: system, protocol, objects, ledger, evidence-graph, spec · updated 2026-07-28T04:33:00.263Z

## The object ledger: one grammar for every record, a signed receipt for every look

Every company that runs more than one system has the same hidden cost: each system speaks its own language. Video talks in frames. Access control talks in events. Payments talk in transactions. Messaging talks in headers and threads. HR talks in rows with soft deletes. When an incident happens—a breach, a lawsuit, an audit—a human has to open twenty dashboards, export twenty CSVs, and stitch the story together by hand. The question "what did we know, and when" takes weeks and is always wrong.

The second problem is newer. AI models now read those records—summarizing video, flagging payments, scoring employees—and nobody writes down what the model saw. There is no receipt. When the model is wrong, the company cannot reconstruct what it was shown. When the model is right, the company cannot prove it. The model is a witness with no memory and no oath.

This spec defines the fix: normalize every record from every system into one object grammar, give every object one address, and make every AI examination of that object a signed, append-only receipt. Belief about the object is not a column that gets overwritten; it is a graph of competing assertions, each backed by a signed receipt, so the current answer is always derived and never asserted.

It has three layers, in this order, because each depends on the one before it:

1. **Object grammar** — what exists, and what can be acted on. Section 1.
2. **Ledger** — what every actor actually did to an object, permanently. Section 2.
3. **Evidence graph** — what is currently believed about an object, computed from the ledger, never overwriting it. Section 3.

Proof of coverage — whether a declared set of objects received a required examination — is one mechanism inside layer 2, covered in Section 6.

A companion object grammar and invocation protocol already runs in production on this site at `/a/oip` — the tool-invocation half of this system. This document specifies the record-ingestion and evidence-graph half.

![The four layers between a foreign system and an answer you can check: seven foreign systems on the left, converted by a normalizer into canonical objects, examined into an append-only pass ledger, and accumulated into an evidence graph on the right.](https://miscsubjects.com/img/spec/object-ledger-fig1.svg)
## 1. Ingestion and normalization

### 1.1 What goes in

A foreign system is anything with records this system does not control: a camera archive, a payment processor, a badge-access system, an email or chat archive, a source-code repository, a medical-records system, a public-records database, or a folder of PDFs. None of these systems change to participate. Records are pulled through whatever interface already exists — an API, a database replica, a file export — and converted at that boundary.

### 1.2 The canonical object

Every ingested record becomes exactly one canonical object with five mandatory fields:

| Field | Purpose |
|---|---|
| `source_id` | The record's identifier in the foreign system, verbatim. |
| `canonical_id` | The identifier this object uses everywhere else in this system. |
| `type` | One of the object grammar's families (Section 1.4), or `unresolved`. |
| `source_hash` | sha256 of the original bytes, so the object can be checked against the source at any later time. |
| `translation_version` | Which version of the mapping rule produced this object. |

```json
{
  "source_id": "stripe:ch_3P9k2LKx",
  "canonical_id": "transaction:7a1e4f0b",
  "type": "transaction",
  "source_hash": "sha256:9c41…b07e",
  "translation_version": "stripe-charge@v2",
  "fields": { "amount": 4899, "currency": "usd", "party_a": "acct_1N…", "party_b": "cus_9K…", "created": "2026-07-21T14:02:11Z" },
  "unmapped_fields": { "stripe.balance_transaction": "txn_3P9k2L…", "stripe.payment_method_details.card.checks": { "cvc_check": "pass" } }
}
```

Nothing in `fields` is guessed. A Stripe field with no place in the canonical transaction schema goes to `unmapped_fields` rather than being dropped — a mapping that silently discards data is undetectable by anyone who only reads the canonical object afterward.

### 1.3 What happens when the mapping is uncertain

Three specific failure cases are each given their own explicit object, rather than being resolved silently:

- **A record that fits no known type.** Stored as `type: "unresolved"` with the raw payload attached. It is never forced into the nearest-fitting type, because a forced fit corrupts every later query that trusts the `type` field.
- **Two records that might be the same real-world entity.** A badge scan and a payment made nine seconds later, both naming "J. Rivera" — stored as a separate `identity_claim` object: `{ "object_a": "person:44f1", "object_b": "person:91ac", "method": "name+timestamp-proximity", "confidence": 0.71 }`. The two source objects are never merged. Merging destroys the ability to later discover the match was wrong; the claim sits beside both objects and can itself be contradicted.
- **A schema field with no canonical target.** Recorded, not discarded (1.2).

Entity resolution — deciding whether two records describe one real entity — is a studied statistical problem with a nonzero error rate at any scale, measured directly in practice. A coverage claim built on top of unexamined identity conflicts silently inherits that error rate. Recording every conflict as its own object is the only way an auditor can find out how many conflicts existed and how they were resolved.

[[embed:source:p11]]

[[embed:source:p12]]

[[embed:source:m4]]

### 1.4 The object grammar

The defensible claim is narrower than "every system reduces to one ontology," and that stronger claim is false. The claim actually made: many foreign systems contain recurring structural families, and those families can be normalized through reusable templates while everything that does not fit stays visible as an exception.

| Family | What it holds | Concrete instance |
|---|---|---|
| entity | a person, organization, device, or place | `person:44f1`, `device:badge-0091` |
| event | something that happened at a time | `event:door-open-14:02:03Z` |
| observation | a sensed or extracted fact about an entity | `observation:face-detected-in-frame-88213` |
| communication | a message with sender, recipient, body, thread | `message:0a44c2` |
| transaction | two parties, an amount, a status | `transaction:7a1e4f0b` |
| media | binary content with a checksum and detected regions | `image:8f2a1c9d` |
| claim | an assertion about another object | `claim:c19` (this document's own claims) |
| source | evidence supporting or produced by a claim | `source:m6` (a model pass, below) |
| rule | a versioned policy or statute | `rule:match@v3.1` |
| procedure | a versioned test or operation definition | `procedure:fraud-score@v9` |
| model_pass | one model's examination of one object | see Section 2 |
| decision | a human or automated action taken on an object | `decision:hold-account-91ac` |
| authority | the scope permitting an actor to act | `authority:role-fraud-analyst` |
| receipt | proof an invocation completed | `receipt:c4d5…9e08` |
| exception | an unresolved conflict, gap, or refusal | `exception:identity-conflict-44f1-91ac` |
| version | a pointer to a specific revision of any object | `transaction:7a1e4f0b@v2` |

Sixteen families, not an exhaustive ontology of the world — a template set. A foreign system that produces something with no good fit produces an `unresolved` object (1.3) and a new template gets written, reviewed, and versioned. That is the entire extension mechanism; there is no larger schema waiting to be discovered.

![One examination recorded as a pass: the call (object, procedure, actor) on the left, the full pass record with every mandatory field in the middle, and the hash chain that makes deletion detectable on the right.](https://miscsubjects.com/img/spec/object-ledger-fig2.svg)

## 2. The ledger

### 2.1 What a ledger event contains

Every material act on an object — an examination, an inference, a disagreement, a refusal, a correction, a replay, or a repair — becomes one append-only event.

```json
{
  "object_id": "transaction:7a1e4f0b",
  "object_version": "v1",
  "actor": "fraud-model-c@operator-4",
  "procedure": "fraud-score@v9",
  "authority": "role-fraud-analyst",
  "input_hash": "sha256:1b9f…7d21",
  "output": "flagged",
  "evidence": "sha256:d6a2…44e1",
  "started_at": "2026-07-27T18:04:11.221Z",
  "status": "completed",
  "parent_invocation": null,
  "replay_of": null,
  "repair_of": null,
  "prev": "sha256:aa01…4f6b",
  "hash": "sha256:bb02…7c1d"
}
```

| Field | Why it exists |
|---|---|
| `actor` | Which model, endpoint, or human acted — an identity, not a display name. |
| `procedure` | Versioned. "Reviewed for fraud" is unrepeatable; `fraud-score@v9` resolves to a stored definition. |
| `authority` | The scope that permitted this act, so an audit can ask whether the actor was allowed to act at all. |
| `input_hash` | Binds the record to the exact bytes examined at that moment. |
| `status` | `completed`, `failed`, or `refused` — a refusal is a first-class event, not a missing row. |
| `parent_invocation`, `replay_of`, `repair_of` | Link a corrected or repeated action back to the one it responds to, so a chain of corrections is traceable. |
| `prev`, `hash` | The append-only chain: deleting this row breaks every hash after it. |

### 2.2 What this is not

| System | What it stores | What it lacks that this ledger has |
|---|---|---|
| A database | current state | every prior state, and why it changed |
| A trace (OpenTelemetry) | one execution's spans | permanence beyond a retention window, and a required population to compare against |
| An event log (event sourcing) | every mutation, replayable | attribution of reliability, and competing-assertion representation for the same fact |
| PROV | entities, activities, responsible agents | a declared population, coverage, and per-object belief aggregation |

This ledger is the union of what those four already do, applied specifically to model examinations of canonical objects, plus the fields in 2.1 that none of the four individually require. Full source cards for OpenTelemetry and event sourcing:

[[embed:source:p2]]

[[embed:source:p4]]

### 2.3 A refusal is a recorded event

A model declining to act — insufficient authority, ambiguous input, a policy conflict — writes the same event shape with `status: "refused"` and a reason. Without this, a system cannot distinguish "this object was never examined" from "this object was examined and the model declined to act," and those are different facts with different consequences for a later audit.

## 3. The evidence graph

### 3.1 A model's conclusion is a claim, not a fact

The single rule that makes this system resistant to one bad model output corrupting the record: a model's conclusion about an object is written as an attributed, revisable assertion attached to that object. It is never written into the object's own fields as settled fact.

```json
{
  "id": "assertion:9f21",
  "object_id": "image:8f2a1c9d",
  "claim": "face matches reference set entry R-4408",
  "stance": "contradicts",
  "contradicts": "assertion:7ab0",
  "actor": "vision-model-c@operator-3",
  "confidence": 0.31,
  "authority": "role-investigator",
  "independence": "trained_separately_from:7ab0.actor",
  "ts": "2026-07-27T18:12:04Z"
}
```

`assertion:7ab0`, made earlier by a different model, said `no_match`. Both assertions persist. Neither is deleted when they disagree.

### 3.2 Computing a current belief without deleting what produced it

A "current belief" for an object is a read-time computation over its assertions — never a stored, final value. This is the one place this specification names its own unsolved problem plainly: combining many assertions into one belief is an instance of the belief-revision problem, and no belief-revision rule is neutral. Every rule weights some inputs over others, and every weighting is attackable by whoever controls the inputs.

[[embed:source:p14]]

[[embed:source:m3]]

A recency-and-trust-weighted rule is concretely vulnerable to adversarial recency-inflation: a late, low-trust, undisclosed-derivative assertion outranks an earlier high-quality consensus because recency dominates the score, and an independence penalty cannot catch a derivation the submitter does not disclose. This is not a hypothetical caveat; it is the specific attack against the specific rule quoted above.

### 3.3 The query this buys that nothing else answers

[[embed:source:m6]]

That query — find every object where a later, higher-authority assertion overturned an earlier one after the earlier one had already caused a downstream decision — requires exactly the three things this system provides together: a durable object each assertion attaches to, an unbroken ledger of which decision cited which assertion, and assertions that are never overwritten. None of the systems in Section 7 store all three.

## 4. Signed model work

### 4.1 What a signature proves

A signed pass — the pairing of a ledger event (2.1) with the model or execution identity that produced it — establishes exactly five things: which model or execution identity produced the record, which object and object version it examined, which procedure it used, what output it produced, and when it ran, plus whether the record has been altered since (via the hash chain).

in-toto and SLSA establish the general shape being borrowed here: bind a claim to a content digest and name the actor, rather than to a filename or a free-text description.

[[embed:source:p5]]

[[embed:source:p6]]

### 4.2 What a signature does not prove

It does not prove the conclusion is true. It does not prove the input source was itself truthful. It does not prove the procedure applied was the correct one for the situation. It does not prove all relevant evidence was included. And it does not prove the operator did not selectively omit other passes over the same object while presenting this one.

That last gap is not theoretical:

[[embed:source:m2]]

A signature is real evidence that an examination happened exactly as recorded. It is not evidence that the examination was the whole story, or the right one to cite.

## 5. Proof of coverage

Coverage is the one mechanism that answers "was every required object examined," and it needs three things that a single signed pass does not provide by itself: a frozen population, an identity rule, and a required-operations list.

```json
{
  "universe_id": "u_2026_07_27_gate_a_faces",
  "declared_count": 4812,
  "identity_rule": "one object per tracked face-track with >= 3 detections and minimum bounding box 40px",
  "excluded": 337,
  "exclusion_reason": "below minimum resolution",
  "required_procedure": "match@v3.1"
}
```

```sql
SELECT u.declared_count,
       COUNT(DISTINCT p.object_id) FILTER (WHERE p.output <> 'error') AS examined,
       u.declared_count - COUNT(DISTINCT p.object_id) FILTER (WHERE p.output <> 'error') AS missing
FROM universe u LEFT JOIN pass p
  ON p.universe_id = u.id AND p.procedure = u.required_procedure
WHERE u.id = 'u_2026_07_27_gate_a_faces';
-- 4812 | 4790 | 22
```

A signed pass proves one examination happened. Coverage proves whether the required population received the required examinations — a query against two tables, not a claim any model makes about its own completeness.

## 6. Scale

[[embed:source:m1]]

Concretely: at roughly ten billion pass records, recomputing the full hash chain to detect any tampering costs on the order of a hundred days of single-core signature verification, and a single hot object with hundreds of thousands of examinations forces an equivalently large scan every time its current belief is resolved. A production deployment therefore needs a compaction or snapshot layer — periodic, signed summaries of an object's assertion state that later queries read by default, with the raw chain kept for audit and available on demand. This document specifies the raw layer; it does not specify the compaction layer, which is unresolved.

![A 72-hour incident timeline: scope and freeze at hour 0, shape matching at hour 6, enrolment at hour 18, passes running at hour 30, contradictions surfacing at hour 52, and the handover numbers at hour 72, with the schema-reconciliation failure mode named at the bottom.](https://miscsubjects.com/img/spec/object-ledger-fig3.svg)

## 7. One complete event, hour by hour

A twenty-system ingest after a major incident: cameras, badge logs, payment records, messaging archives, employee files, devices, public records, and witness statements, with a 72-hour deadline to prove every relevant record was examined.

**Hour 0 — scope and freeze.** Twenty systems listed. Access confirmed on fourteen, refused on three, unknown on three pending legal review. The identity rule for "one relevant record" is written and signed before any ingestion begins.

**Hour 6 — shape matching.** The fourteen accessible systems map onto six of the sixteen object families in Section 1.4. Two systems need a new template written and reviewed. Every field with no canonical target is logged, not dropped (1.2).

**Hour 18 — enrolment.** 2,412,006 objects hashed and counted. The universe is frozen. 311,004 records are excluded by the identity rule, each with a stated reason (mostly: below-threshold image resolution, duplicate badge scans within the same second).

**Hour 30 — passes running.** Three independent models examine the same enrolled objects under versioned procedures. 6.1 million pass records written. A coverage query runs every fifteen minutes against the live table.

**Hour 52 — contradictions surface.** 1,204 objects now carry two model assertions that disagree. This is not an error state; it is the evidence graph doing its job (Section 3). All 1,204 are queued for human review by rule, not by whoever happens to notice.

**Hour 72 — handover.** 2,412,006 enrolled · 2,398,771 examined · 13,235 unresolved and individually named · 1,204 contested and queued · 3 systems refused access, listed by name. Every number in that sentence is a query against the object table and the pass table. None of it is a model's summary of its own work.

[[embed:source:m4]]

The honest failure mode of this whole scenario is not a shortage of storage or a shortage of model calls. It is the schema-reconciliation step at hour 6 — if that step is faked or rushed, every later number, including "2,398,771 examined," is decoration sitting on top of a broken join.

## 8. Applications

| Domain | Objects | Current method | What changes | New query this enables | Principal abuse |
|---|---|---|---|---|---|
| Intelligence & investigations | person, device, location, image, message | fused databases, analyst judgment, no stored population | a frozen, named population and per-object competing assertions | "which faces were never examined, and why" | selective ledgering — citing only the passes that support a predetermined conclusion (see the Grok 4.5 pass, Section 4.2) |
| Fraud | account, transaction, device, dispute | one model score per transaction, thin logs | every detector's judgment attached to the same account/transaction objects, disagreement preserved | "which flagged accounts had a later model reverse an earlier hold" (the GLM Flash pass, Section 3.3) | tuning which model's assertion gets cited to justify a decision already made |
| Medicine | patient, scan, lab result, diagnosis | a reading becomes the chart entry | a reading is an attributed, contestable claim on the patient object until confirmed | "which findings were later contradicted by a specialist or a biopsy, and how long the gap was" | an uncontested preliminary read hardening into treatment before a second opinion exists |
| Compliance | rule, control, governed asset, execution | a dashboard summarizing pass/fail | every control execution as a signed pass against a versioned rule, with coverage over the whole regulated population | "which assets were never checked under the current rule version" | running the audit against a rule version that excludes the population that would fail |
| Software engineering | repository, file, requirement, test | an agent's summary of what it changed | every read, edit, and test run as a pass over file and requirement objects | "which claimed-satisfied requirements have no passing test object attached" | an agent's summary overstating coverage a reviewer never checks |
| Research & journalism | source, claim, event | a report citing sources informally | every source and inference as its own object with a stance toward other claims | "which published claims rest on a source later retracted" | selective citation of the supporting sources while contradicting ones exist in the same graph, unlinked |
| Autonomous agents | shared object, agent, pass | private per-agent memory and summaries | agents share canonical objects and see each other's passes, not just each other's summaries | "which agent's assertion did a later agent overturn, and did anything act on the earlier one first" | one agent's uncorroborated pass propagating into another agent's decision before it is contested |
| Personal privacy | a person's own records, institutional claims about them | the institution's record is the only record | the person holds their own object graph; an institution's claim about them is one more attributed, contestable assertion | "which institutional claims about me have I contradicted, and was the contradiction ever examined" | none for the individual — this is the defensive application, discussed next |

## 9. Dual use

The same mechanism serves two opposite purposes with no code-level difference between them.

An institution can fuse someone's payment, location, communication, and access records into canonical objects, run models over them, and accumulate an evidentiary case — this is the coming AI-fusion problem in its concrete, mechanical form.

Two separate 2024 FTC orders document this already happening in the commercial location-data market: data brokers reselling location tied to medical clinics, religious sites, and shelters, with no per-disclosure signed record of who bought what and why.

[[embed:source:e1]]

[[embed:source:e2]]

Two GAO reports document the same absence inside government use: federal facial-recognition searches run for years with no stored training requirement and, for most agencies, no specific civil-rights policy — exactly the missing procedure record and missing coverage record this specification requires by default.

[[embed:source:e3]]

[[embed:source:e4]]

The identical mechanism run in the other direction lets a person maintain their own object graph, hold an institution's claims about them as attributed, contestable assertions rather than accepted fact, and attach counterevidence to the same object the institution's claim lives on. The risk does not disappear in this direction either: it shifts entirely to who controls ingestion, identity resolution, authority, visibility, retention, challenge rights, aggregation rules, and downstream action.

Nothing in the architecture decides which direction it runs. That is decided entirely by who controls ingestion, identity resolution, authority, visibility, retention, challenge rights, aggregation rules, and downstream action. EFF's independent reading of the same enforcement actions is useful because it names exactly those levers as the ones that were uncontrolled.

[[embed:source:e5]]

## 10. Prior art

| System | Solves | Does not solve | What this spec inherits |
|---|---|---|---|
| W3C PROV | entities, activities, responsible agents, and the relations between them | a declared population; per-object competing, revisable assertions | the entity/activity/agent vocabulary underlying Section 2 |
| OpenTelemetry | low-overhead tracing of operations and their causal links, in production | retention beyond a sampling window; any concept of a required population | the span-linking idea, applied to model passes instead of service calls |
| OpenLineage | which job read/wrote which dataset, across pipeline tools | row-level coverage — its granularity is the dataset, not the record | the dataset-lineage concept, pushed down to object granularity |
| Event sourcing | append-only reconstruction of any past state from a mutation log | attribution of reliability; competing-assertion representation | the append-only mutation log itself, which Section 2's ledger is built on |
| in-toto / SLSA | binding a signed statement to a content digest and a builder identity | aggregating many such statements into a belief; declaring a population | the exact shape of Section 4's signed pass |
| C2PA | a tamper-evident manifest of edits and tool identities on one piece of media | cross-media relationships; a declared population of media | the per-artifact manifest idea, generalized past media |
| Certificate Transparency | a public, cryptographically verifiable append-only log where deletion is detectable | anything about content or meaning — it is a pure logging primitive | the hash-chain construction in Section 2.1, at object scale instead of internet scale |
| LangGraph persistence | checkpointing one agent's own execution for pause/resume/rollback | multiple independent agents sharing state as objects, or recording their disagreement | the checkpoint-as-durable-state idea, extended to cross-agent shared objects in Section 8 |
| Palantir Foundry Ontology | unifying enterprise data into typed objects, links, and actions at production scale | (as documented) an open, independently implementable spec; per-examination model attestation as a first-class primitive | the object-and-link modeling approach, published here as an open specification instead |
| Record linkage / entity resolution | the statistical theory of matching records to real-world entities, since 1969 | what to do with the object once matched — linkage stops at the match decision | the confidence-scored identity_claim object in Section 1.3 |
| Schema matching | proposing correspondences between two schemas, automatically or semi-automatically | what happens to fields with no correspondence | the versioned mapping concept; unmapped_fields is this spec's explicit answer to the gap |
| Belief revision | the formal theory of updating beliefs under new, possibly contradicting information | providing one neutral aggregation rule — none exists | the honest statement, in Section 3.2, that this is unsolved here too |

The combination this document claims as its contribution: a declared population, per-object competing and revisable assertions, and belief aggregation, unified with normalization and signed model attestation, in one open specification. No single system above provides all three; several provide one or two. Whether an unpublished or classified system already combines all of this has not been checked — patent filings and defense-sector literature were not searched for this document, and that is a stated limitation, not a claim of novelty.

Full source cards for every system in the table above, in the same order:

[[embed:source:p1]]

[[embed:source:p2]]

[[embed:source:p3]]

[[embed:source:p4]]

[[embed:source:p5]]

[[embed:source:p6]]

[[embed:source:p7]]

[[embed:source:p8]]

[[embed:source:p9]]

[[embed:source:p10]]

[[embed:source:p11]]

[[embed:source:p12]]

[[embed:source:p13]]

[[embed:source:p14]]

## 11. Article as proof

This document is itself an instance of what it specifies. Its 35 numbered claims are addressable claim-objects. Its fourteen prior-art sources and five regulatory sources are evidence-objects. The six model answers collected during this document's own drafting are signed pass-objects, each attached to the specific claim it supports, each carrying the model identity, the exact question, the exact answer, and a timestamp — reproduced below in full, plus the pass recording this document's own authorship. A reader can move, right now, from any claim above to its source, from a source to the model pass that produced it, and from that pass to the exact quote and verdict — the traversal this specification describes in Section 3.3, demonstrated rather than only asserted.

[[embed:source:m1]]

[[embed:source:m2]]

[[embed:source:m3]]

[[embed:source:m4]]

[[embed:source:m5]]

[[embed:source:m6]]

[[embed:source:a1]]


## Sources

1. W3C PROV-DM: The PROV Data Model — https://www.w3.org/TR/prov-dm/
2. OpenTelemetry tracing specification — https://opentelemetry.io/docs/specs/otel/trace/api/
3. OpenLineage object model — https://openlineage.io/docs/spec/object-model
4. Event Sourcing — https://martinfowler.com/eaaDev/EventSourcing.html
5. in-toto attestation framework — https://github.com/in-toto/attestation
6. SLSA v1.0 provenance specification — https://slsa.dev/spec/v1.0/provenance
7. C2PA technical specification 2.1 — https://c2pa.org/specifications/specifications/2.1/index.html
8. Certificate Transparency (RFC 6962) — https://www.rfc-editor.org/rfc/rfc6962
9. LangGraph persistence and checkpoints — https://langchain-ai.github.io/langgraph/concepts/persistence/
10. Palantir Foundry Ontology overview — https://www.palantir.com/docs/foundry/ontology/overview
11. Fellegi–Sunter record linkage / entity resolution survey — https://en.wikipedia.org/wiki/Record_linkage
12. A Practitioner's Guide to Evaluating Entity Resolution Results — https://arxiv.org/abs/1509.04238
13. Schema matching — https://en.wikipedia.org/wiki/Schema_matching
14. Belief revision — https://en.wikipedia.org/wiki/Belief_revision
15. FTC order prohibits X-Mode/Outlogic from selling sensitive location data — https://www.ftc.gov/news-events/news/press-releases/2024/01/ftc-order-prohibits-data-broker-x-mode-social-outlogic-selling-sensitive-location-data
16. FTC action against Mobilewalla for selling sensitive location data — https://www.ftc.gov/news-events/news/press-releases/2024/12/ftc-takes-action-against-mobilewalla-collecting-selling-sensitive-location-data
17. GAO-23-105607: Facial Recognition Services — federal law enforcement training and civil-liberties gaps — https://www.gao.gov/products/gao-23-105607
18. GAO-24-107372: Facial Recognition Technology — federal agency follow-up on civil-rights training — https://www.gao.gov/products/gao-24-107372
19. Federal regulators limit location brokers from selling your whereabouts: 2024 in review — https://www.eff.org/deeplinks/2024/12/federal-regulators-limit-location-brokers-selling-your-whereabouts-2024-review
20. GLM 5.2 on the hot-object failure mode
21. Grok 4.5 on who buys this first, and how they'd abuse it
22. Kimi K3 on the belief rule and its failure mode
23. MiniMax M3 on what breaks first at 72 hours
24. Kimi K2.6 on what an organization loses by adopting this
25. GLM Flash on the query that is impossible today
26. Claude Opus 5, writing and ledgering this specification


---

# Proof of coverage: how to prove an AI examined every record it was given

slug: proof-of-coverage · https://miscsubjects.com/a/proof-of-coverage · tags: system, protocol, objects, ledger, audit · updated 2026-07-28T03:24:44.947Z

## What proof of coverage is

Proof of coverage is a way of recording machine work so that a stranger can check whether every item that was supposed to be examined actually was. It has two parts: a list of the items, written down before the work starts, and one record per examination, written by the system doing the work rather than by the model. Completeness is then a subtraction between the two lists.

The problem it solves comes up whenever software is asked to look at many things and report back. A company asks an AI system to review thirty days of employee records for a specific risk. The system answers: reviewed, three concerns found. Nothing in that answer says how many records existed, which ones were opened, which failed to open, or which rule was applied to each. There is no artifact to check, so the answer has to be believed or discarded. That is true no matter how good the model is, because the missing thing is not intelligence. It is bookkeeping.

[[embed:source:s7]]

A second model, asked the same question with none of the first answer in front of it, stopped in the same place.

[[embed:source:s8]]

## The four objects

Everything below is built out of four record types. Nothing else is required.

| Object | What it is | Written when |
|---|---|---|
| **universe** | A named set of items to be examined, with a frozen count and the rule that decides membership | Once, before any work |
| **object** | One item in that set, with a stable id and a hash of its content | Once per item, at enrolment |
| **procedure** | A versioned description of the test to apply — the prompt, the model, the threshold, the tool | Once per version |
| **pass** | One examination of one object by one actor under one procedure, with the result | Once per examination |

"Universe" is the load-bearing word. It is the denominator: the number the coverage percentage is divided by. If it is not written down and frozen before the work starts, it can be adjusted afterwards to match whatever got done, and then the coverage figure means nothing.

## What a pass record contains

The record is written by the execution environment — the code that calls the model — never by the model itself. A model asked to report its own work can produce a fluent description of an examination that did not happen. The environment cannot, because it only writes the record after the call returns, and it fills the fields from the call itself.

```json
{
  "universe_id": "u_2026_07_27_gate_a_faces",
  "object_id": "face:8f2a1c9d4b6e0175",
  "object_hash": "sha256:8f2a1c9d…0a1b2c",
  "procedure": "match@v3.1",
  "actor": "vision-model-a@operator-1",
  "input_envelope_hash": "sha256:1b9f…7d21",
  "output": "no_match",
  "confidence": 0.02,
  "started_at": "2026-07-27T18:04:11.221Z",
  "duration_ms": 412,
  "receipt": "sha256:c4d5…9e08",
  "prev": "sha256:aa01…4f6b",
  "hash": "sha256:bb02…7c1d"
}
```

Field by field, and why each one is not optional:

| Field | Why it is there |
|---|---|
| `object_hash` | Binds the result to the exact bytes examined. Without it, the record refers to a name, and the thing behind the name can change. |
| `procedure` | Versioned. "Reviewed for risk" is not checkable; `match@v3.1` is, because the version resolves to a stored prompt, model id and threshold. |
| `actor` | Which model, which endpoint, which operator ran it. Two actors disagreeing about one object is a fact worth keeping. |
| `input_envelope_hash` | Hash of everything sent — prompt, parameters, attachments. Makes the call repeatable by a third party. |
| `output` | A value from a fixed set the procedure declares, not free text. Free text cannot be counted. |
| `receipt` | The provider's own identifier for the call, when one exists. Independent corroboration that the call occurred. |
| `prev`, `hash` | The chain. Explained below. |

[[embed:source:s9]]

The same requirement exists in software supply-chain security, where a signed statement binds a claim to the digest of the artifact rather than to its filename. The shape is borrowed, not invented.

[[embed:source:s2]]

## The chain, and what it stops

Each pass record hashes its own contents together with the hash of the record before it:

```js
// hash = sha256(prev + canonical_json(record_without_hash))
async function chain(prev, record) {
  const body = JSON.stringify(record, Object.keys(record).sort());
  const bytes = new TextEncoder().encode(prev + body);
  const digest = await crypto.subtle.digest('SHA-256', bytes);
  return [...new Uint8Array(digest)].map(b => b.toString(16).padStart(2, '0')).join('');
}
```

Without the chain, the easiest way to produce a perfect coverage report is to delete the passes that failed. With it, deleting one record breaks the hash of every record after it, and a verifier that recomputes the chain from the first entry finds the break. The chain does not prevent deletion. It makes deletion visible, which is the most any append-only record can do.

## Coverage is a query, not a claim

With the four object types in place, "did it examine everything" stops being a question about the system's honesty:

```sql
SELECT
  u.declared_count,
  COUNT(DISTINCT p.object_id) FILTER (WHERE p.output <> 'error') AS examined,
  u.declared_count - COUNT(DISTINCT p.object_id) FILTER (WHERE p.output <> 'error') AS missing
FROM universe u
LEFT JOIN pass p
  ON p.universe_id = u.id
 AND p.procedure = 'match@v3.1'
WHERE u.id = 'u_2026_07_27_gate_a_faces';
```

A result of `4812 | 4790 | 22` is a real answer: twenty-two enrolled objects have no successful pass under that procedure, and a second query names them. "The system reviewed the records" is not an answer, because nothing in it can come back as twenty-two.

The same table answers the questions that matter after the fact. Which objects were examined more than once. Where two actors disagreed. Which objects nobody touched.

| Actor | Object | Passes | Result |
|---|---|---|---|
| `vision-model-a@operator-1` | `face:F-1842` | 1 | no match |
| `vision-model-b@operator-2` | `image:I-9921` | 1 | no match |
| `vision-model-c@operator-3` | `image:I-9921` | 2 | match, confidence 0.31 |
| `doc-model-a@operator-4` | `receipt:R-4408` | 1 | accepted |

Two actors reached opposite conclusions about `image:I-9921`. In separate systems that contradiction never meets. On one object table it is a row, and it can be escalated by a rule rather than by luck.

## The identity rule sets the denominator, so it is written first

The hardest part of this method is not the storage. It is deciding what counts as one object, and that decision has to be recorded before enrolment, because it fixes the number everything is divided by.

For faces in footage: is a person appearing in eleven frames one object or eleven? Is a face at nine pixels wide an object or an unusable detection? Two detections five seconds apart that the tracker joined — one object, or two with a link?

The rule is stored on the universe as text a person can read and as code that runs:

```json
{
  "id": "u_2026_07_27_gate_a_faces",
  "declared_count": 4812,
  "frozen_at": "2026-07-27T18:00:00Z",
  "identity_rule": "One object per tracked face-track with >= 3 detections and minimum bounding box 40px. Tracks broken by more than 2s of occlusion are separate objects. Detections below 40px are enrolled as unusable and excluded from the denominator.",
  "identity_rule_impl": "sha256:9c41…b07e",
  "excluded": 337,
  "exclusion_reason": "below minimum resolution"
}
```

Note `excluded`. Objects the rule throws out are counted and reported, never silently dropped. A universe that declares 4,812 objects and 337 exclusions is checkable. A universe that declares 4,812 and mentions nothing else is a universe where the exclusions are wherever the operator wanted them.

## Enrolling a system it does not cooperate with

The other system does not need to adopt any of this. Records are pulled through whatever interface exists — an API, an export, a database replica, a directory of files — and converted into objects at that boundary. Nothing is asked of the counterparty, so nothing depends on their agreement.

That is affordable because record shapes repeat. Different products, same structure:

| Shape | Fields that always exist | Examples |
|---|---|---|
| Collection | cursor or offset, page size, total or last-page marker | almost every list API |
| Record with identity | id, created, updated, owner | employee, customer, patient rows |
| Transaction | two parties, amount, currency, timestamp, status | payment processors, banks, ledgers |
| Message | sender, recipients, body, thread id, timestamp | email, chat, ticket systems |
| Media with detections | binary, checksum, detected regions with coordinates and confidence | image and video pipelines |
| Operation | inputs, actor, authority, effects, outputs | logs, audit trails, job runners |

[[embed:source:s10]]

An enrolment template is written once per shape. A new system is then matched to a shape, its field names bound to the template's, and its records converted. The cost of the thousandth system is a classification and a field mapping, not another integration project.

The remaining difficulty is real but ordinary: throughput, deduplication when the same underlying thing appears in two systems, ordering when timestamps disagree, and identity resolution when two records may be the same person. None of it changes the four object types.

## What it costs to store a billion passes

Rates below are Cloudflare's published D1 prices, page last updated 2026-04-21. A pass record with full 64-character hashes serialises to 659 bytes.

| Item | Arithmetic | Result |
|---|---|---|
| Writing 1,000,000,000 passes | 1,000 million × $1.00/million | **$1,000 once** |
| Storing them | 1e9 × 659 B = 659 GB; (659 − 5) × $0.75 | **$490.50 / month** |
| Full-table coverage recount | 1e9 rows read × $0.001/million | **$1.00 per recount** |
| Indexed coverage query on one universe | thousands of rows read | fractions of a cent |

[[embed:source:s6]]

A recount over a billion examinations costs a dollar. The reason this is not already normal practice is not the bill.

## What this does not prove

Coverage is proof that a procedure ran over every enrolled object. It is not proof that the procedure was right.

[[embed:source:s11]]

Ten models can apply the same wrong rule, sign cleanly, and produce a ledger with 100% coverage over a bad conclusion. Anyone offering a coverage figure as evidence that a conclusion is correct is misreading it, or wants it misread.

What the structure does buy is that the wrong conclusion now has an address. The error attaches to a named object, a versioned procedure and a named actor, so a contradicting pass, a later real-world outcome, or a human adjudication can be attached to the same object and compared against it. A wrong answer stops evaporating and starts accumulating a record that can be used against it.

## What already exists

None of the parts are new. The gap is specific and worth naming precisely.

[[embed:source:s1]]

PROV models entities, activities and agents — the pass, in other words — and has no concept of a declared set that the activities were supposed to cover.

[[embed:source:s3]]

SLSA and in-toto bind a claim to a digest and name the builder, which is exactly the shape a pass record needs, applied to build artifacts.

[[embed:source:s4]]

Traces record operations and their relationships, are commonly sampled, and expire on a retention policy. Nothing in a trace says how many spans should have existed.

[[embed:source:s5]]

Lineage tracks which job read which dataset. It answers questions at table granularity, not per row.

The missing piece across all of them is the same: a frozen, stored count of what was supposed to be examined, sitting next to the records of what was. Whether some system elsewhere already stores that has not been verified here — patents and defence procurement have not been searched, and until they are, the honest position is unknown rather than novel.


## Sources

1. W3C PROV-DM: The PROV Data Model — https://www.w3.org/TR/prov-dm/
2. in-toto attestation framework: signed statements about software artifacts — https://github.com/in-toto/attestation
3. SLSA v1.0 provenance specification — https://slsa.dev/spec/v1.0/provenance
4. OpenTelemetry tracing specification — https://opentelemetry.io/docs/specs/otel/trace/api/
5. OpenLineage object model — https://openlineage.io/docs/spec/object-model
6. Cloudflare D1 pricing — rows written, rows read, storage — https://developers.cloudflare.com/d1/platform/pricing/
7. GPT-5.6 on the declared universe
8. Kimi, given the same question and none of the first answer
9. GPT-5.6 refuses the self-report
10. Kimi on how few shapes there are
11. The strongest objection on the page

