# Cattle discovery index

The Worker indexes deployment events for the configured Base trial factory. It
does not cache balances, debt, health factors or order previews. The browser
validates the checkpoint against Base, reads every block after it through its
current snapshot, and reads the lens at that current snapshot. An unavailable,
stale, mismatched or oversized index causes a full scan from factory deployment.
Use `app.html?preview=address&address=thetadeployer&index=0` to force that fallback.

## Service

- Worker: `cattle-index`; database: `cattle-index` (dedicated D1, APAC).
- Route: `https://thetanuts.finance/dev/cattle/api/registry`.
- Diagnostics: `https://thetanuts.finance/dev/cattle/api/status`.
- Cron: every minute, UTC. Each invocation certifies at most three 5,000-block
  intervals through head minus six blocks. Initial backfill takes several ticks.
- The browser reads through head minus two blocks. The four-block difference and
  cron delay are always covered by direct reads; the cron frontier is never
  treated as the current portfolio state.
- API is GET-only, with 10-second HTTP caching. No public backfill/admin endpoint.
- A 15-minute freshness bound returns 503 for a stale index. A warming index also
  returns 503. Neither condition is represented as an empty registry.

## Certification and recovery

Each interval has two log witnesses on distinct provider hosts. Each witness
checks the expected block hash on that exact endpoint before and after its log
request. Matching empty arrays from lagging providers cannot advance coverage.
The event set is compared in full; the known D/E trial events are coverage
anchors. Every new event is verified against the clone, factory implementation,
creation receipt and factory address prediction before insertion.

A 90-second lease excludes overlapping jobs; the run has a 55-second deadline.
A single SQL INSERT and its triggers atomically insert events and advance the
cursor. The trigger fences source version, lease token, lease expiry and previous
cursor. A failed event insertion rolls back the interval and all its events.

Before each commit, the Worker rechecks the previous committed block and the
interval end. It validates the run head before publishing readiness. A detected
reorg resets the entire prefix atomically and rebuilds; it never leaves a newer
checkpoint on top of old-branch events. The reset uses UPDATE RETURNING because
D1 change counts include triggered deletes. Registry metadata and events are
read in one SQL statement so the API cannot combine different database snapshots.

## Operations

Run from this directory with the existing Cloudflare account authentication:

```sh
wrangler types --include-runtime=false
wrangler deploy --dry-run --outdir /tmp/cattle-indexer-build
wrangler deploy
```

For an initial installation only, create the dedicated D1 database, set its ID in
`wrangler.jsonc`, then run `wrangler d1 execute cattle-index --remote --file schema.sql`.
Do not apply this schema to another app's database. Cron configuration can take
up to 15 minutes to propagate; the frontend remains usable through direct reads.

Tests: `npm test` from `cattle/` (Node 22 with experimental SQLite). Tests execute
the actual SQL triggers with D1-style trigger-inclusive change counts, actual
Worker entry points and the actual frontend validator. They cover lease loss,
atomic rollback, partial-run recovery, reorg timing, stale API responses, exact
tail coverage, fresh balance block selection and full-chain fallback. Browser
checks use the real `/dev/cattle/` route; no local server is required.

## Live verification — 14 September 2026

The initial cron backfilled the two deployments in five successful ticks, without
errors. The API then returned both events at creation blocks 51,221,788 and
51,283,978. While it warmed up, the browser's 503 fallback still found both.

The first measured indexed page used cursor 51,290,649 and directly read the
remaining 23 blocks through 51,290,672. Network inspection confirmed both log
witnesses requested exactly [51,290,650, 51,290,672], and both lens calls used
51,290,672. No console errors occurred. It made 30 total RPC requests.

A separate comparison fixed the read block at 51,290,704. Indexed and full
discovery returned identical position objects, two positions and no failures.
One unthrottled run took 7.6 seconds with the index versus 8.5 seconds for full
discovery. Per-position verification and account reads still dominate this small
trial. The optimization reduces historical log work; it does not promise an
instant account read. All 60 scenario tests pass, and independent review cleared
the reorg, D1 change-count and shared-witness-anchor fixes.

References: [Cloudflare Cron Triggers](https://developers.cloudflare.com/workers/configuration/cron-triggers/),
[D1 database API](https://developers.cloudflare.com/d1/worker-api/d1-database/),
[Workers guidance](https://developers.cloudflare.com/workers/best-practices/workers-best-practices/).

## September 21 perpetual deployment

The current configuration deploys `cattle-index-period` with its own D1 database
(`6d39a597-fda3-477e-a7ad-f7d7362f65db`) on `/dev/cattle/api/v2/*`. It indexes factory
`0x985b605ad55f76c2acaa672861866a8a77208a2e` from block 51,589,857, using the deployed
e4c87fc ABI and the S/L creation anchors. Initial backfill uses at most three
1,000-block intervals per cron. Ordinary reads start with PublicNode to reserve
BlockPI/BLXR capacity for the two independent log witnesses.

The existing `cattle-index` Worker and database remain on `/dev/cattle/api/*`,
serving the earlier factory to the legacy reader. That deployed bundle is unchanged;
do not redeploy it using the new factory configuration. Both generation reads use
the same browser snapshot block. Each index supplies only its own certified prefix;
the browser reads the tail, or the whole generation when that index is unavailable.

The source version stays 1 because the registry wire format is unchanged; factory,
deployment block and known anchors bind each registry to its own generation.
`schema.sql` now initializes the **new** database only. Earlier operational notes
above describe the original dated index and are historical.
