▸ features & updates usage
new: genuinely free AI models are live — try surp/free + see live budgets · token-gating prototype · vote on SRP

features & updates

surp.ivc.lol changelog — what shipped and when.

This page tracks day-to-day progress on surp.ivc.lol: the x402-paywalled LLM gateway, cache flywheel rewards, token-gated access, free AI models, and the provider health board. Updates are newest first.

this is a living project. Features ship as they're ready, not on a fixed release schedule. If something breaks, it gets fixed the same day. Check /status for live system health, or /health for per-model TPS and latency.

2026-08-13

investor pitch deck live at /pitch

Apple-style 10-slide pitch deck for the Base Ecosystem Fund application, served at https://surp.ivc.lol/pitch. One idea per slide, no bullets, huge type on black with phosphor accents. Scrolls horizontally with snap, arrow keys, and nav dots; one wheel notch glides one slide with an eased animation; fixed 'back to surp' link. Print CSS exports a clean one-slide-per-page PDF.

merged community PR #1 — live TTFT/TPS/F1000 metrics feed

Merged and deployed the first community contribution, authored by armchairfuturist-code (github.com/armchairfuturist-code), who asked ivcained to merge it. Lands metrics_core.py (StreamSample + compute_tps/compute_f1000_h with ai-speedometer parity), a write-behind SQLite metrics store in its own metrics.db (drop-on-full, WAL, 14-day raw retention), a stream tap that measures wall-clock TTFT to the first token, a token-gated SSE feed at /api/metrics/stream (Bearer + hmac.compare_digest), a live section on /dashboard (TTFT / TPS / F1000 cards, per-model table, canvas sparkline, SSE-over-fetch client), and optional strategy=f1000 routing that picks the best F1000 model from live samples with fallback to cheapest. Author credited in the README contributors section.

2026-08-12

import-collision fixes — chat path restored

Found and fixed two module-alias collisions that shadowed imports: 'import studio as st' overrode stats (breaking every chat completion with AttributeError), and 'import performance_page as pp' overrode proposal_page (breaking /proposal). Studio re-aliased to stdo, performance_page to pfp, and a static scan now guards against any handler using a logger it never defined.

2026-08-11

Surp Studio — all-in-one AI creative workspace

Launched a full creative suite at /app/studio with chat, text-to-image, image-to-image, text-to-video, and a private gallery. Chat defaults to surp's treasury-sponsored free tier with a pick-your-model dropdown (surp/free, surp/free-coding, surp/free-fast); clicking the 'ask anything' placeholder focuses the input. Image pane ships 8 one-click presets (photoreal, anime, pixel art, cyberpunk, watercolor, 3D render, line art, oil painting) plus a comfy-style advanced panel (steps, guidance, seed, strength, aspect). Creations are private by default with opt-in sharing via unguessable token URLs.

studio generation on Surplus Intelligence (no FAL key needed)

Rewired the studio's image/video generation to the Surplus Intelligence OpenAI-compatible API using the same key the resolver already uses — verified live that venice-flux-1.1-pro and 111 other image/video models generate real media. FAL stays as an optional fallback, mock last.

studio generation is x402-paywalled with 5% router markup

Hard per-generation charging: studio image/video generation now runs the same two-phase x402 flow as chat. First call returns 402 with the exact USDC price (Surplus media-unit price + 5% router markup, floored at 1¢), the wallet signs an EIP-3009 transfer, and the gateway verifies and settles on Base before generating. Zero-balance accounts can no longer generate for free — the quote includes live balance and the UI warns before signing. Creation records store paid_usdc and tx_hash.

Surplus SettlementV2-inspired fee transparency + retry

Studied Surplus's on-chain settlement contract (0x0770...e6cc137, UUPS proxy with feeMultiplier/flatFee) and adopted the useful parts without copying the risky standing-allowance design: a public GET /api/studio/quote endpoint exposes the full fee breakdown (seller amount, markup bps, markup USD, flat fee, total) like their calculateFee view call, and settlement now retries with exponential backoff (5 attempts) instead of failing on the first transient error. Kept per-request signatures, which their own docs call the safer pattern.

SRP token contract proposal page + deploy vote

Community proposal at /proposal/srp: should surp deploy SurpRewardToken (SRP) as a real ERC-20 on Base? Lists the contract design (OZ ERC20 + Permit + AccessControl + Pausable, 1B cap, immutable), benefits, risks, and the gas-fee analysis of standing approvals vs per-request signatures. Advisory vote with 4 options (deploy mainnet now / testnet first / wait / don't deploy), isolated from the existing flywheel proposal via multi-proposal voting with automatic DB migration.

Surp Value Index (SVI) — one score per model + your own routing lens

Built a composite score (weighted geometric mean, 0-100) combining price, verified speed, and intelligence into a single SVI per model. Leaderboard at /svi with benchmark submission. Then added routing modes: send surp_mode=cost|value|speed|intel|balanced or custom surp_weights='0.3:0.4:0.3' and the gateway routes by your lens instead of the default — verified live across all modes, with the winning reason included in the 402 body.

'Phosphor Terminal' redesign — one UI language for the whole site

Unified every page into a distinctive phosphor-terminal design language: pure-black background, phosphor-green accents, JetBrains Mono, CRT scanlines. The React dashboard got a sectioned left sidebar (account: overview/wallet/api keys/activity/usage; explore: all site pages with docs highlighted), active-page phosphor glow, mobile off-canvas drawer, and a top bar with wallet widget and logout.

2026-08-10

Privy login + embedded wallets + full user dashboard

Added real accounts: login with email/passkeys/Farcaster via Privy, an embedded wallet per user, and a full dashboard at /app — wallet page with QR code and add/withdraw USDC, API keys with per-key budgets and one-time-show secrets, live activity feed, lifetime usage table with Basescan tx links, and recharts graphs (total spend, marketplace savings, requests, token volume, top models, top API keys). Auth verifies Privy JWTs locally via JWKS with a fallback REST path; user API keys (surp_ prefix, SHA-256 hashed) authenticate Bearer requests.

2026-08-08

verified LLM throughput benchmarks — real output TPS

Built a live benchmark runner that streams real requests through surp and measures generation throughput (output tokens/second), TTFT, and throughput-per-dollar. Verified deepseek-v4-flash-0731 at p50 90.6 TPS (mean 100.2, max 122.3) at $0.0648/M, and deepseek-v4-flash at p50 94 TPS @ $0.0162/M. Public leaderboard at /performance, API at /api/benchmarks. Corrected the health board terminology: RPS (requests/second) is different from output TPS (generated tokens/second) — both are now measured.

2026-08-07

cache-affinity auction — ad-network model for cached inference

Identified the core market-design flaw: orderbooks price the listing, not the fill, so they can't surface cache-state differences between providers. Built the gateway-side infrastructure for an ad-network-style auction: privacy-preserving prefix hashing (like cookie IDs), latency-based cache inference (post-bid verification), Vickrey-style proposed bids that discount below list price for models with demonstrated cache affinity, and dishonesty detection via latency. Live explainer at /auction, data in /api/stats under cache_affinity.

2026-08-06

free model health board + provider TPS/latency tracker

Built a live provider health board that tracks TPS, p50/p95 latency, failure rate, and a composite health score for every model surp routes — metrics the Surplus Intelligence marketplace dashboard does not expose. Health scores feed back into routing: cheap-and-flaky loses to slightly-pricier-but-reliable.

per-class free routes: surp/free-coding + surp/free-fast

Added two new treasury-sponsored free routes with their own price ceilings: surp/free-coding (filters to coder/codex models, $0.50/M cap) and surp/free-fast (filters to mini/nano/lite/flash, $0.05/M cap). Both gracefully fall back to the general free pool if no models qualify.

free-tier API keys with elevated budgets

Heavy free users can now create a free-tier API key (POST /api/free-key) with elevated daily request and token budgets, replacing the default IP-based limits. Keys are validated in the free request path.

streaming support on the free path

The free tier now accepts streaming requests with a conservative token buffer (200 tokens above the max output cap) so concurrent streams don't starve the global budget.

free-to-paid conversion tracking

When a free user hits the budget wall, the gateway records a conversion event. Public stats show distinct free users, conversion count, rate, and which paid combos they upgraded to.

OmniRoute-inspired free-tier intelligence integration

Integrated MIT-licensed free-tier catalog intelligence from github.com/diegosouzapw/OmniRoute: pool-deduped recurring token budgets, recurring vs one-time separation, uncapped-provider honesty, and ToS risk labels. Public inference remains treasury-sponsored, not proxy-resold third-party credentials.

genuinely free AI models — surp/free

Launched surp/free: treasury-sponsored free LLM inference with no x402 payment, no API key, automatic live fallback across cheap liquid models, and strict daily/per-IP budgets. Live at /free-models with real-time budget tracking.

2026-08-05

token-gated API access prototype

Built an NFT/token-gated eligibility layer: callers with an X-Wallet header and sufficient token balance bypass x402 payment. Read-only balanceOf check, cached for 60s, fail-closed. Community feedback open at /token-gating.

cache flywheel reward ledger (SRP)

Implemented off-chain SRP reward tokens: cache writers earn 1 SRP per cached token, cache authors earn 2 SRP per reused token, readers earn 0.5 SRP. Backed by 50% of gateway markup earmarked to a rebate pool. Public vote on Juicebox/RevNet direction at /proposal.

cache-aware sticky routing + exact-response cache

Two-layer cache engine: sticky routing keeps the last model if it stays within 30% of the live cheapest (preserves provider prefix cache), and exact-response cache returns identical deterministic responses at 0.1¢ instead of 1¢ (90% discount). Live at /cache.

SQLite database separation + fault isolation

Split the monolithic combos.db into three separate files (combos, rewards, cache) to eliminate write-lock contention. All reward and cache operations are now wrapped in fault-isolating try/except so a locked DB never breaks a paid request.

dynamic per-page SEO titles + og tags

Every page now has a unique, keyword-targeted and matching og:title/og:description. The status page browser tab updates live with request count and cache hit rate.</p></div><div class='feature-entry'><h3>5 SEO keyword landing pages</h3><p class='dim'>Created /x402, /x402-llm-api, /x402-gateway, /pay-per-request-llm-api, and /cheapest-llm-api — each 1300-1700 words with FAQ schema, canonical tags, and 18-21 internal links. Sitemap grew to 17 URLs.</p></div><div class='feature-entry'><h3>global notification banner</h3><p class='dim'>Added a site-wide dismissible announcement banner that appears on every page, with localStorage persistence. Version-keyed so new announcements resurface for users who dismissed the previous one.</p></div><div class='feature-entry'><h3>Farcaster mini app + JFS signing</h3><p class='dim'>Built a Farcaster mini app at /miniapp with fc:miniapp meta tags, live ticker, and composeCast share button. Manifest signed with the user's FID 191554 JFS signature.</p></div><div class='feature-entry'><h3>resolver sellability fix</h3><p class='dim'>Fixed best-reasoning and best-fast returning model '?' by adding an is_sellable() filter that skips models with total_cap=0 or healthy_seller_count=0. All 15 combos now resolve to servable models.</p></div><div class='feature-entry'><h3>nginx header split for x402 vs content</h3><p class='dim'>Rewrote nginx config so only /api/ and /v1/ routes get x402 Access-Control-Expose-Headers; content pages, sitemap, and robots get clean headers. Resolved Google Search Console 'Sitemap could not be read'.</p></div><div class='feature-entry'><h3>dashboard, API keys, combo history, rate limiting</h3><p class='dim'>Added /dashboard wallet lookup, prepaid API key mode (Authorization: Bearer), combo history snapshots every 5 minutes, and IP sliding-window rate limiting (60 req/60s, fails open).</p></div><div class='feature-entry'><h3>animated terminal hero + mobile nav</h3><p class='dim'>Homepage now has an animated terminal hero showing the full x402 cycle: curl → 402 → signing → settled → routed → code streams. Made nav mobile-friendly with flex-wrap and media queries.</p></div><div class='feature-entry'><h3>ELI5, quick-start, 404 page, SEO meta</h3><p class='dim'>Added an ELI5 section with 3 cards, a quick-start curl example, a themed 404 page, meta description + OG/Twitter tags, and truncated the combo pool tables (128KB → 42KB homepage).</p></div><div class='feature-entry'><h3>x402 end-to-end payment cycle working</h3><p class='dim'>Fixed 402 challenge header (PAYMENT-REQUIRED), inbound payment header (PAYMENT-SIGNATURE), and facilitator verification to use client-signed payload.accepted with EIP-712 domain. Full cycle verified: client signs → gateway decodes → facilitator verifies → settles.</p></div><div class='feature-entry'><h3>status page + /api/stats</h3><p class='dim'>Added /status page and /api/stats JSON with total requests, 24h requests, USDC settled, unique wallets, system health, top combos, and cache metrics.</p></div><div class='feature-entry'><h3>SQLite stats persistence</h3><p class='dim'>Created stats.py with WAL-mode SQLite, 4 tables (requests, combo_snapshots, api_keys, rate_limits), thread-safe with busy_timeout. Also added rate-limit transaction leak fix (upsert + guaranteed rollback).</p></div></div><div class='feature-day'><h2>2026-08-04</h2><div class='feature-entry'><h3>Farcaster mini app + brand assets</h3><p class='dim'>Generated brand assets (icon.png, hero.png, og-image.png), built the /miniapp page (424x695 modal, no nav/scanlines), and added .well-known/farcaster.json manifest.</p></div><div class='feature-entry'><h3>FSB (Full Self Browsing) integration</h3><p class='dim'>Installed fsb-mcp-server globally, added to Hermes config under mcp_servers, saved the FSB workflow skill, and verified the bridge on localhost:7225 (WS) + 127.0.0.1:7226 (HTTP).</p></div><div class='feature-entry'><h3>connect your Hermes button + dashboard JS fixes</h3><p class='dim'>Added /connect route with a 3-step connect guide and yellow CTA on the homepage. Fixed dashboard JS ($ is not defined) and global link colors (was invisible dark blue).</p></div><div class='feature-entry'><h3>initial gateway + 15 combos live</h3><p class='dim'>Stood up the x402-paywalled LLM gateway on aiohttp with 15 routing combos (best/pro × coding/reasoning/fast/vision/chat + aliases), served at https://surp.ivc.lol/ with HTTPS via Let's Encrypt.</p></div></div> <h2>how to follow along</h2> <ul style="margin-left:20px;line-height:1.8;"> <li><a href="/status">/status</a> — live request counts, cache hit rate, USDC settled, reward pool</li> <li><a href="/health">/health</a> — per-model TPS, p50/p95 latency, failure rate, composite health score</li> <li><a href="/free-models">/free-models</a> — live free-tier budget, eligible models, served models today</li> <li><a href="/api/stats">/api/stats</a> — machine-readable version of everything above</li> <li><a href="/proposal">/proposal</a> — vote on the cache flywheel reward direction</li> <li><a href="/token-gating">/token-gating</a> — feedback on the NFT-gated access prototype</li> </ul> <p class="dim">related: <a href="/docs">API docs</a> · <a href="/cache">cache-aware routing</a> · <a href="/about">about</a></p> <footer> <div class="footer-links"> <a href="https://farcaster.xyz/ivc" target="_blank" rel="noopener" aria-label="Farcaster" class="social-link"> <svg width="18" height="18" viewBox="0 0 1000 1000" fill="currentColor"><path d="M257.778 155.556H742.222V844.445H671.111V528.889H670.414C662.554 441.677 589.258 373.333 500 373.333C410.742 373.333 337.446 441.677 329.586 528.889H328.889V844.445H257.778V155.556Z"/><path d="M128.889 253.333L157.778 351.111H182.222V746.667C169.949 746.667 160 756.616 160 768.889V795.556H155.556C143.283 795.556 133.333 805.505 133.333 817.778V844.445H382.222V817.778C382.222 805.505 372.273 795.556 360 795.556H355.556V768.889C355.556 756.616 345.606 746.667 333.333 746.667H306.667V253.333H128.889Z"/><path d="M675.556 746.667C663.282 746.667 653.333 756.616 653.333 768.889V795.556H648.889C636.616 795.556 626.667 805.505 626.667 817.778V844.445H875.556V817.778C875.556 805.505 865.606 795.556 853.333 795.556H848.889V768.889C848.889 756.616 838.94 746.667 826.667 746.667V351.111H851.111L880 253.333H702.222V746.667H675.556Z"/></svg> </a> <a href="https://x.com/ivcained" target="_blank" rel="noopener" aria-label="X (Twitter)" class="social-link"> <svg width="15" height="15" viewBox="0 0 24 24" fill="currentColor"><path d="M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-5.214-6.817L4.99 21.75H1.68l7.73-8.835L1.254 2.25H8.08l4.713 6.231zm-1.161 17.52h1.833L7.084 4.126H5.117z"/></svg> </a> <a href="https://github.com/ivcained/surp-router" target="_blank" rel="noopener" aria-label="GitHub" class="social-link" title="source on GitHub"> <svg width="16" height="16" viewBox="0 0 16 16" fill="currentColor" aria-hidden="true"><path d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0016 8c0-4.42-3.58-8-8-8z"/></svg> </a> </div> surp.ivc.lol · aggregating the aggregator · built for the community · <a href="https://github.com/ivcained/surp-router">source on GitHub</a> · <a href="https://github.com/x402-foundation/x402">x402 protocol</a> · <a href="https://www.surplusintelligence.ai">surplus intelligence</a> <p class="dim" style="margin-top:8px;font-size:10px;"> x402 LLM gateway · OpenAI-compatible API · pay per request in USDC on Base · cheapest AI models from the Surplus Intelligence marketplace · no account needed · no API key required </p> <p class="dim" style="margin-top:6px;font-size:10px;"> <a href="/x402">what is x402</a> · <a href="/x402-llm-api">x402 LLM API</a> · <a href="/x402-gateway">x402 gateway</a> · <a href="/pay-per-request-llm-api">pay-per-request LLM API</a> · <a href="/cheapest-llm-api">cheapest LLM API</a> · <a href="/free-models">free AI models</a> · <a href="/health">health board</a> · <a href="/performance">verified TPS</a> · <a href="/app">login & wallet</a> · <a href="/features">features & updates</a> · <a href="/auction">cache auction</a> · <a href="/cache">cache-aware routing</a> · <a href="/proposal">reward proposal</a> · <a href="/token-gating">token-gating</a> · <a href="/pitch">pitch deck</a> </p> </footer> </div> </div> </div> </div> <script> // Announcement banner: dismiss persists in localStorage so a user who // has seen the update isn't nagged on every page load. Bump the version // suffix when the announcement content changes so it resurfaces. (function() { var v = "v2-free-models"; try { if (localStorage.getItem("surp-announce-" + v) === "dismissed") { var b = document.getElementById("announce-banner"); if (b) b.classList.add("hidden"); } } catch (e) { /* localStorage may be blocked; banner just stays visible */ } })(); function dismissAnnounce() { var b = document.getElementById("announce-banner"); if (b) b.classList.add("hidden"); try { localStorage.setItem("surp-announce-v2-free-models", "dismissed"); } catch (e) {} } // Mobile sidebar drawer — open/close with hamburger, click backdrop, or Escape. function toggleSidebar() { var sb = document.querySelector(".site-sidebar"); var bd = document.getElementById("site-backdrop"); if (!sb || !bd) return; var open = sb.classList.toggle("open"); bd.classList.toggle("open", open); } function closeSidebar() { var sb = document.querySelector(".site-sidebar"); var bd = document.getElementById("site-backdrop"); if (sb) sb.classList.remove("open"); if (bd) bd.classList.remove("open"); } document.addEventListener("keydown", function(e) { if (e.key === "Escape") closeSidebar(); }); // Close drawer when any menu link is clicked (mobile) AND persist the sidebar // scroll position so it does not jump back to the top on the next page. // We store it in sessionStorage keyed per-path so navigating back restores the // exact scroll place the user was at, without caching stale positions forever. var SB_SCROLL_KEY = "surp-sidebar-scroll"; // Restore the saved sidebar scroll position. Runs immediately (the script sits // at the end of <body> so the sidebar DOM exists) with retries so font/layout // settling that clamps scrollHeight never wins. (function() { var sb = document.querySelector(".site-sidebar"); if (!sb) return; var saved = null; try { saved = sessionStorage.getItem(SB_SCROLL_KEY); } catch (e) {} if (saved === null) return; var target = parseInt(saved, 10) || 0; var restore = function() { if (!sb.isConnected) return; var max = sb.scrollHeight - sb.clientHeight; // Clamp both bounds: target may be stale/negative if the menu shrank. sb.scrollTop = Math.min(Math.max(0, target), max); }; restore(); window.setTimeout(restore, 100); window.setTimeout(restore, 400); if (document.readyState !== "complete") { window.addEventListener("load", function() { window.setTimeout(restore, 100); }); } })(); document.addEventListener("DOMContentLoaded", function() { var sb = document.querySelector(".site-sidebar"); var links = document.querySelectorAll(".site-menu a"); links.forEach(function(a) { a.addEventListener("click", function() { closeSidebar(); if (sb) { try { sessionStorage.setItem(SB_SCROLL_KEY, String(sb.scrollTop)); } catch (e) {} } }); }); // Mark the current page's menu link as active so it lights up with a glow. var current = document.body.getAttribute("data-active-path") || window.location.pathname; if (current === "" ) current = "/"; links.forEach(function(a) { var href = a.getAttribute("href") || "/"; if (href === current) { a.classList.add("active"); } }); }); </script> </body> </html>