Perishable / skelfresearch
Architecture

The proxy holds the key. The client holds a receipt that expires.

Perishable is a process between your frontend and an OpenAI-compatible API. Here is exactly what moves where, and — just as important — what this design does not promise.

Request flow

Two round-trips, one secret that never travels

browser ──[ POST /session + fingerprint + entropy ]──> perishable │ ├── check entropy looks human ├── issue short-lived JWT (bound to fingerprint) ▼ browser ──[ POST /openai/v1/... + Bearer JWT ]──> perishable ──[ Authorization: Bearer sk-… ]──> upstream ▲ └── rate-limit per fingerprint, refuse expired / mismatched tokens

The sk-… key exists only on the right-hand side of the proxy. The browser sees a JWT that stops working within minutes.

Piece by piece

What each stage does

1 · Entropy handshake

The client SDK collects real input signals before requesting a session. The proxy checks that entropy looks human before it mints anything, raising the cost of headless automation.

2 · Fingerprint-bound JWT

On success the proxy issues a short-lived JWT bound to the client fingerprint. A token lifted to another browser fails the binding check.

3 · Proxied call

The client calls the OpenAI-compatible surface with the JWT. The proxy validates it, applies the rate limit, and forwards upstream with the real key attached server-side.

4 · Expiry & refresh

The SDK refreshes the session before it expires (expiryBuffer). A leaked token is useless within its short TTL — the perishable part.

Honest threat model

What this stops — and what it doesn't

Stops

  • Your sk-… key ending up in a JS bundle, iOS binary, or Electron app.
  • A scraped long-lived credential being replayed for weeks.
  • Casual, high-volume abuse from headless scripts and copied tokens.

Does not stop

  • A determined attacker driving a real browser — they can still get a session; they just can't get a million cheaply.
  • The need for per-user auth on sensitive actions. A JWT here is not a login.
  • Spend tracking — Perishable is not an analytics or observability layer.

Fingerprint + entropy is bot-resistance, not bot-proofing. It raises the cost of casual abuse, which is the common failure mode — not the cost of a determined adversary.

Run it yourself

Follow the quickstart, or read the endpoint and config reference in the docs.