Angel Campa
Colour theme

WorkThe Cloudflare pivot

CAMAudit v2

Read a commercial lease and its CAM reconciliation statement side by side, and produced a reviewed report identifying the dollar amount a tenant may have been overbilled.

Ran on
Cloudflare Workers
Ran
Started February 2026
Domain
Commercial real estate compliance

Built with

  • Cloudflare Workers
  • Workflows
  • TypeScript
  • Queues
  • R2
  • Browser Rendering
  • Supabase Postgres

Hosted services

  • Workflows
  • Queues
  • R2
  • Browser Rendering
  • Supabase Postgres

The decision

Models read documents in CAMAudit; they never compute. The rule is stated once and holds everywhere: “AI extracts and classifies; TypeScript calculates. […] The LLM never performs calculations.” Twenty deterministic rule modules do the arithmetic, and a model only ever returns a field or a classification, never a number it derived itself.

That split survived a full rewrite of the extraction and detection engine, from a planned Python implementation to TypeScript. The division of labor did not move when the runtime did.

CAMAudit v2 is the second engine for this problem. The first is CapVeri, and this one started in a new repository from an empty tree rather than as a fork of it: separate roots, no shared history, no shared objects in either direction. Forking would have carried CapVeri’s answers across as the starting point, and the whole argument of both products is that a number has to be derivable from the lease and the statement it describes. Two independent implementations that agree are evidence. One implementation and a copy of itself are not.

Six independent checks stand between what a model returns and a dollar figure reaching a report: a findings critic, an adversarial judge, a math-proof verifier, a citation-coverage check, cross-validation between the lease and the statement, and a pro-rata guard.

Architecture

The system is built on Cloudflare Workers. Five Workflows orchestrate the pipeline from document upload to report, and a queue (producer, consumer, and a dead-letter queue) carries the asynchronous work. Documents live in R2, a Browser Rendering binding produces PDF output, and the database is Supabase Postgres with row-level security enabled on every table.

A golden-fixture regression corpus of 24 synthetic lease-and-statement pairs, 20 of them supplying the same reconciliation statement in more than one file format, checks the pipeline end to end so a planted defect runs more than one ingestion path. Two of the 24 pairs plant no errors at all: negative controls that measure false positives as well as recall.

A direct-to-tenant product lane, LeaseAudit, was consolidated into this codebase in July 2026, so the same engine and database serve both an advisor-facing workflow and a self-serve one.

By the numbers

Each figure carries where it came from and when it was measured. Open one to see the command behind it, where the repository recorded a command.

Detection rule modules
20 deterministic modules
Provenance

Source cloudflare/api/src/services/detection/rules/ (private repository)

ls cloudflare/api/src/services/detection/rules/*.ts

Measured

Durable workflows
5
Provenance

Source docs/engineering/metrics.md § Architecture (private repository)

node scripts/portfolio-metrics.mjs --write

Measured

Async job topology
1 queue, with a producer, a consumer, and a dead-letter queue
Provenance

Source cloudflare/api/wrangler.jsonc (private repository)

Measured

Golden fixture corpus
24 synthetic lease-and-statement pairs, 20 of them supplying the same reconciliation statement in more than one file format
Provenance

Source e2e/golden/CORPUS-REPORT.md for the 24 pairs; e2e/fixtures/ counted per pair for the file formats (private repository)

Measured

Guards on model output
6 independent, named checks between a model's extraction and a dollar figure reaching a report
Provenance

Source docs/engineering/trustworthy-ai-output.md (private repository)

Measured