feat: enrich servers with CPU cores, threads, generation, and benchmark scores (#256)
* feat: enrich servers with CPU cores, threads, generation, and benchmark scores
Add CPU enrichment from Geekbench data for both auction and standard servers.
Enables filtering by core/thread count, sorting by CPU score, and displays
CPU details (cores/threads, architecture family, GB6 score) on server cards
and detail drawer.
- Add generate_cpu_specs.py to fetch and match Geekbench data
- Enrich auction servers in update_incremental.py via cpu-specs.json
- Enrich in CF Worker via AuctionDataTransformer.lookupCpuSpecs()
- D1 migration for cpu_cores, cpu_threads, cpu_generation, cpu_score columns
- Add cores/threads range sliders to filter UI
- Add CPU Score sort option
- Add CPU row to ServerFactSheet (both layouts)
- Add cpuCores/cpuThreads alert matching in MATCH_ALERTS_SQL
- Weekly GHA workflow to update cpu-specs.json from Geekbench
* fix: resolve CI failures for CPU enrichment
- Copy cpu-specs.json into worker/src/ instead of symlinking through
gitignored data/ directory
- Fix prettier formatting
* fix: resolve flaky Playwright tests
- landing.spec.ts: update text matchers to match current page content
("Dedicated Servers" not "Dedicated Server Auctions",
"check cloud availability" not "check cloud server availability")
- server-interactions.spec.ts: remove non-existent table lookup in
drawer, wait for loading state instead of arbitrary timeout
- advanced-filtering.spec.ts: replace networkidle + waitForTimeout with
waitForFilterUpdate helper that polls until count stabilizes
- fixtures.ts: add waitForFilterUpdate helper for reliable DuckDB waits
feat(auth): migrate authentication to Better Auth
Replaces the hand-rolled session/email-code auth with Better Auth 1.6.25,
backed by D1 (natively supported — no community adapter needed).
- migration 0016 adds account/verification, extends user, rebuilds session.
user is ALTERed additively, never rebuilt: four tables reference user(id)
ON DELETE CASCADE, so recreating it would cascade-delete every alert.
Verified against a seeded copy of the schema — all five FK relationships
survive, user.id values preserved, foreign_key_check clean.
- session is rebuilt (Better Auth needs a NOT NULL UNIQUE token existing rows
cannot supply), which also corrects user_id's declared type from INTEGER to
TEXT. Existing sessions are dropped: cutover forces a re-login.
- email OTP replicates the previous flow exactly (6 digits, 15 minutes, same
mail copy) so the login UI is unchanged.
- column names mapped explicitly to snake_case; Better Auth's `casing` option
is declared in its types but never read at runtime in 1.6.25.
Requires BETTER_AUTH_SECRET to be set before deploy.
feat(mcp): public MCP server with authenticated alert management
POST /mcp speaks stateless Streamable HTTP JSON-RPC. Read tools work with no
credentials; presenting a valid MCP access token additionally exposes alert
management, so tools/list is conditional on the Authorization header.
- search_auctions / get_auction serve from the KV snapshot, so MCP traffic
reads zero D1 rows. cloud_availability proxies the worker.
- list_alerts / create_alert / delete_alert are gated on a Better Auth MCP
session. Migration 0017 adds the OAuth provider tables (camelCase, unlike the
rest of the schema: MCPOptions has no field-mapping escape hatch and nothing
in the app queries them).
- Alert tools take the same flat schema as search_auctions and build the
ServerFilter server-side, in defaultFilter's key order — idx_price_alert_
user_id_filter is UNIQUE on the serialised string, so key order is
load-bearing.
Encodings were taken from MATCH_ALERTS_SQL rather than the UI, and verified
against production: RAM is log2(GB), disk sizes are units of 500 GB, and
price_alert.price is GROSS whole euros with vat_rate as a percentage — not
cents and not a decimal rate, as the spec had assumed.
Also fixes baseURL, which was pinned to the production origin. Better Auth's
isAuthPath() rejects a mismatched origin, so every /api/auth/* route 404'd on
localhost and would have on any preview deployment.