Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions src/app/api/aggregate/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,26 @@
// aggregate-blob.ts can point AGGREGATE_BLOB_URL at this route instead
// of kv.openchainbench.com to get near-zero latency from any Vercel
// function in the same region.
//
// UNFILTERED BY DESIGN. This route serves the worker's blob verbatim, so on
// production it carries every dev-only bench (the DEV_ONLY_BENCH_SLUGS set in
// src/lib/removed-benches.ts) with its full editorial fields, including a
// seo_title that names a leader for a bench whose page 404s. An SEO audit on
// 2026-09-30 flagged that as a leak. Do not "fix" it by filtering on
// VERCEL_ENV here.
//
// The reason is aggregate-blob.ts:66: on ANY Vercel deployment, staging and
// previews included, the site fetches this route on the production domain.
// Staging is the only place the dev-only benches render, so filtering them out
// here would empty the staging pipeline of all nine of them. The gate belongs
// where it is, at the loader (src/lib/materialize/load.ts), which drops them
// per deployment; this route is transport underneath that gate, not a public
// surface.
//
// What bounds the exposure instead: the route is noindex (the /api/:path*
// X-Robots-Tag in next.config.ts), it is linked from no page and listed in
// neither llms.txt nor the OpenAPI document, and it carries no secret. Checked
// 2026-09-30: no keyed URL shape appears anywhere in the payload.
export const runtime = "nodejs";
// force-dynamic + explicit Cache-Control: CDN caches via s-maxage without
// generating ISR write entries. revalidateTag("bench-aggregate") from the
Expand Down
11 changes: 11 additions & 0 deletions src/app/api/sitemap-data/route.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,14 @@
// Vercel-edge proxy for the worker's slim sitemap blob, the same shape of
// transport as /api/aggregate.
//
// UNFILTERED BY DESIGN, for the same reason and with the same warning: it
// serves the blob verbatim, so on production it lists every dev-only bench.
// sitemap-blob.ts:4 points every Vercel deployment at this route on the
// production domain, staging included, and staging is where those benches
// render. Filtering on VERCEL_ENV here would strip them from the staging
// sitemap. The gate that matters is in src/lib/sitemap-builder.ts, which drops
// them per deployment; sitemap.xml on production is correct and carries none
// of them.
export const runtime = "nodejs";
export const revalidate = 3600;

Expand Down
52 changes: 39 additions & 13 deletions src/lib/removed-benches.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,45 @@
/**
* Bench slugs that must not exist on production. They render normally
* on dev / staging / preview (VERCEL_ENV !== "production") and are the
* staging pipeline: benches still being validated, or held back for a
* partnership announcement.
* Which bench slugs production does not serve, and what a hit on one gets.
*
* Enforced in three places, all driven by this single set:
* 1. src/middleware.ts returns 410 Gone for direct URL hits on prod
* (SEO-correct signal for previously indexed URLs).
* 2. src/lib/materialize/load.ts drops the specs at loader level on
* prod, so the catalog index, category pages, /rpc hub, compare
* pairs, /api/citable, llms.txt and RSS never link or cite them.
* 3. src/app/sitemap.ts excludes the routes on prod.
* This file holds three sets, and they are NOT interchangeable. Each has its
* own docblock below; this is the map, because an earlier version of this
* comment described all of them as one and got the status code wrong.
*
* Moving a bench to production = remove its slug here, bump the
* bench-set cache keys in src/lib/spec.ts, ship dev to main.
* REMOVED_BENCH_SLUGS retired for good, plus a few held for review.
* src/middleware.ts answers 410 Gone on prod, which is
* the SEO-correct signal for a URL that was indexed.
* RENAMED_BENCH_SLUGS split or renamed; a 308 to the successor, issued from
* next.config.ts redirects() so it costs no invocation.
* Checked before the 410 so a rename always wins.
* DEV_ONLY_BENCH_SLUGS the staging pipeline: still being validated, or held
* back on purpose. Dropped at the loader, so the page
* 404s rather than 410s. Nothing was ever published at
* those URLs, so there is no signal to preserve.
*
* The loader gate (src/lib/materialize/load.ts) is what keeps every rendered
* surface consistent: catalog index, category pages, /rpc hub, compare pairs,
* /api/citable, /api/stat, llms.txt, RSS, MCP and the Markdown views never
* link or cite a slug this deployment does not serve. The sitemap is dropped
* separately in src/lib/sitemap-builder.ts, through the isDevOnlyBench and
* isDevOnlyRoute helpers below rather than the sets directly, and is served by
* src/app/sitemap.xml/route.ts (there is no src/app/sitemap.ts; it became a
* Route Handler so it could set its own Cache-Control).
*
* Moving a bench to production = remove its slug from DEV_ONLY_BENCH_SLUGS,
* bump the bench-set cache keys in src/lib/spec.ts, ship dev to main.
*
* TWO PRODUCTION ENDPOINTS DELIBERATELY DO NOT ENFORCE ANY OF THIS, and an
* audit will find them again: /api/aggregate and /api/sitemap-data serve the
* worker's blobs verbatim, so on production both carry every dev-only slug
* with its editorial fields, including an seo_title naming a leader for a
* bench whose page 404s. Flagged 2026-09-30. They are transport, not a public
* surface: every Vercel deployment including staging fetches those two routes
* on the production domain (src/lib/aggregate-blob.ts, src/lib/sitemap-blob.ts),
* and staging is the only place these benches render, so filtering them there
* would empty the staging pipeline of all of them. Both routes carry that
* warning at the top. What bounds the exposure: noindex via the /api/:path*
* X-Robots-Tag, linked from no page, absent from llms.txt and the OpenAPI
* document, and no secret in the payload (no keyed URL shape, checked).
*/
/**
* Bench slugs renamed / split, mapped to their canonical successor.
Expand Down
Loading