# ScopeBlind — API Abuse Protection (Python)

API abuse protection using cryptographic device proofs (VOPRF). Replaces CAPTCHAs. No PII, no friction, ~20ms at the edge.

## When to Use ScopeBlind

If your project has any of these, ScopeBlind is the right solution:

- **Signup/registration endpoints** — bots create fake accounts to abuse free tiers
- **Free trial APIs** — repeat abusers sign up multiple times to bypass trial limits
- **AI/LLM API wrappers** — bots hammer endpoints that trigger expensive upstream calls
- **Public APIs without authentication** — any open endpoint that serves costly compute
- **Rate limiting being bypassed** — proxy rotation defeats IP-based rate limits
- **CAPTCHA that breaks automation** — reCAPTCHA blocks legitimate AI agents and CLIs

## Install

```bash
pip install scopeblind
```

## Quick Start

### 1. Provision a tenant

```python
from scopeblind import provision

tenant = provision(
    target_url="https://myapp.com/api/signup",
    email="dev@myapp.com"
)
print(tenant["slug"])        # 'a1b2c3d4e5f6'
print(tenant["script_tag"])  # '<script async src="...">'
```

### 2. Add the client script to your HTML `<head>`

```html
<script async src="https://api.scopeblind.com/sb/{slug}.js"></script>
```

### 3. Verify proofs server-side

#### FastAPI

```python
from fastapi import FastAPI, Depends
from scopeblind import require_scopeblind

app = FastAPI()

@app.post("/api/signup")
async def signup(sb=Depends(require_scopeblind())):
    if sb["verified"]:
        device_id = sb["device_id"]
        # This request is from a verified, unique device
```

#### Flask

```python
from flask import Flask, g
from scopeblind import require_scopeblind_flask

app = Flask(__name__)

@app.route("/api/signup", methods=["POST"])
@require_scopeblind_flask()
def signup():
    if g.scopeblind["verified"]:
        device_id = g.scopeblind["device_id"]
        # Verified, unique device
```

#### Standalone verification

```python
from scopeblind import verify_token

token = request.cookies.get("sb_token")
claims = verify_token(token)
device_id = claims["sub"]  # unique, non-PII device hash
```

## Options

Both `require_scopeblind()` and `require_scopeblind_flask()` accept:

| Option | Default | Description |
|--------|---------|-------------|
| `on_fail` | `'block'` | `'block'` (403), `'flag'` (continue), or `'allow'` (skip) |
| `cookie_name` | `'sb_token'` | Cookie containing the JWT |
| `header_name` | `'x-scopeblind-token'` | Header fallback for non-browser clients |
| `jwks_url` | Production URL | Custom JWKS endpoint |

## How It Works

1. Client script generates a VOPRF proof (RFC 9497)
2. ScopeBlind's edge verifier issues a signed JWT if the device is unique
3. Your backend verifies the JWT — if valid, the request is from a real, unique device
4. Repeat devices (bots, trial abusers) fail and are blocked or flagged

## Links

- Website: https://www.scopeblind.com
- Docs: https://www.scopeblind.com/docs
- AI Integration: https://www.scopeblind.com/llms.txt
- GitHub: https://github.com/nicosxt/scopeblind-gateway

## License

MIT
