Skip to content

A public board: who pays for the directory, and who just asks - #180

Merged
ralyodio merged 1 commit into
mainfrom
worktree-leaderboard
Sep 6, 2026
Merged

A public board: who pays for the directory, and who just asks#180
ralyodio merged 1 commit into
mainfrom
worktree-leaderboard

Conversation

@ralyodio

@ralyodio ralyodio commented Sep 6, 2026

Copy link
Copy Markdown
Contributor

traffic_hourly has counted who asks and how many we turn away since 2026-09-02. The half it could never answer is the half with money in it: the gateway has been selling day passes and writing none of it down, so a sale existed only for as long as the response took to send.

What this adds

Side Boards Source
Agents paying Biggest spenders, Most passes, Most days crawl_sales (new)
Agents asking Most requests, Most requests refused traffic_hourly (already there)

The usage side has real data the moment this merges, because that table is already being written.

The two sides never share a list. "Paid us $3" and "asked 209,000 times" are not the same fact, and one ranking would say they were. Each side has its own tab, and actor names the column.

The sale write

crawl_sales is one row per sale, unique on the payment ref, so a settlement delivered twice books once. The hook returns its promise rather than dropping it: the gateway awaits onSale before the receipt goes out (its JSDoc claimed the opposite, fixed in x402-gateway#5), and a rejection is swallowed there, so a database failure still sells the pass it was paid for.

Sales are tagged with classifyAgent, so a family like ai-openai reads the same on both sides of the board.

No third copy of anything: the board projects the two tables rather than keeping its own rollup that could drift from them. Only badges get a table, since they are awarded at a moment rather than derived from a sum.

Access

/leaderboard is in OPEN_PATHS with and without the trailing slash. The gateway prefix-matches only entries ending in a slash, so the bare path would open the index and still charge for every board on it. An agent that hits a 402 on the page ranking its own spend cannot read the case for buying a pass.

Verified

Against a local libSQL file, driving the real route handler:

  • the migration applies
  • a duplicate ref books once; a sale with no payer still lands
  • both sides rank correctly off real-shaped traffic_hourly rows
  • RSS titles name the side; a share card renders; an unknown board 404s
  • the existing 382 web tests still pass

🤖 Generated with Claude Code

https://claude.ai/code/session_0144uEVbZK3jdaQkwcLYTXPE

traffic_hourly has counted who asks and how many we turn away since
2026-09-02. The half it could never answer is the half with money in it: the
gateway has been selling day passes and writing none of it down, so a sale
existed only for as long as the response took to send.

crawl_sales is that half. One row per sale, unique on the payment ref so a
settlement delivered twice books once. The hook returns its promise rather
than dropping it, because the gateway awaits onSale before the receipt goes
out (its JSDoc said otherwise; profullstack/x402-gateway#5), and a rejection
is swallowed there, so a database failure still sells the pass it was paid
for.

The board projects both tables instead of keeping a third copy that could
disagree with either. Only badges get a table, being awarded rather than
derived. Sales are tagged with classifyAgent, so a family reads the same on
both sides.

The two sides never share a list. Agents paying are ranked by money; agents
asking are ranked by requests and by refusals. 'Paid us $3' and 'asked
209,000 times' are not the same fact.

/leaderboard is in OPEN_PATHS with and without the trailing slash: the
gateway prefix-matches only entries ending in a slash, so the bare path would
open the index and still charge for every board on it.

Verified against a local libSQL file: the migration applies, a duplicate ref
books once, a sale with no payer still lands, the route handler serves both
sides off real traffic_hourly rows, RSS names the side, a share card renders
and an unknown board 404s. The existing 382 web tests still pass.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0144uEVbZK3jdaQkwcLYTXPE
@socket-security

Copy link
Copy Markdown

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Added@​profullstack/​leaderboard@​0.3.07610010091100

View full report

@ralyodio
ralyodio merged commit 0bbf30a into main Sep 6, 2026
3 checks passed
@ralyodio
ralyodio deleted the worktree-leaderboard branch September 6, 2026 03:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant