Metadata-Version: 2.4
Name: relintio-agent
Version: 0.9.8
Summary: RelintioAgent in-process agent for Python ASGI runtimes.
License-Expression: LicenseRef-Proprietary
Project-URL: Homepage, https://relintio.com
Project-URL: Repository, https://github.com/Relintio/relintio-python-agent
Project-URL: Issues, https://github.com/Relintio/relintio-python-agent/issues
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: httpx>=0.26
Requires-Dist: cryptography>=42
Dynamic: license-file

# relintio-agent (Python)

> **Note on Features & Quotas**: Advanced features (like Bot Challenge and Custom Shield Pages) are tied to your subscription plan. If you exceed your monthly API quota, the agent will operate in a degraded mode (basic protection) before ultimately failing-open to prevent locking you out of your own site. All configuration rules are centrally managed via the dashboard.

Python in-process agent for ASGI runtimes (FastAPI/Starlette/etc).

## Install

```bash
pip install relintio-agent
```

## FastAPI usage

```py
from fastapi import FastAPI
from relintio_agent.asgi import UltimateProtectorMiddleware

app = FastAPI()

app.add_middleware(
    UltimateProtectorMiddleware,
    license_key="UP_LIVE_...",
    api_url="https://api.relintio.com/v1",
)

```

## Zero-code-ish usage (env wrapper)

If you can change *how* the app is created (but don't want to paste config into code),
wrap the ASGI app using env vars:

```py
import os
from fastapi import FastAPI
from relintio_agent import wrap_asgi_app

app = wrap_asgi_app(FastAPI())

# env:
# UP_LICENSE_KEY=UP_LIVE_...
# UP_API_URL=https://api.relintio.com/v1
```

### Optional: sitecustomize bootstrap

The platform can generate a `sitecustomize.py` helper inside the **Python auto bundle**.
If that file is on `PYTHONPATH`, Python auto-imports it on startup.
Set `UP_ASGI_APP="module:app"` and it will best-effort wrap that object automatically (fail-open).

## Risk Scoring Engine (v0.9.6)

Every request is evaluated using an **additive 0-100 signal-based score**. Signals include:

| Signal | Weight | Description |
|---|---|---|
| Empty User-Agent | +50 | No UA header sent |
| Short User-Agent | +25 | UA < 20 characters |
| No Accept-Language | +20 | Missing browser locale header |
| Generic Accept | +15 | Wildcard `*/*` only |
| Connection: close | +10 | Non-persistent connection |
| POST without Referer | +15 | Form submission without origin |
| Rate burst | +35 | Token-bucket exhaustion |

### Response Tiers

| Tier | Score Range | Behavior |
|---|---|---|
| **ALLOW** | 0–39 | Request proceeds normally |
| **SLOW** | 40–59 | 2-second `asyncio.sleep` to exhaust scanners |
| **CHALLENGE** | 60–74 | Browser verification challenge |
| **DECOY** | 75–84 | Serves fake maintenance page |
| **BLOCK** | 85–100 | Hard block with configured response |

### Token-Bucket Rate Limiter

Default: **8 tokens/sec**, burst capacity of **24**. Route-aware multipliers give extra capacity to static assets. Memory-safe with 5-minute eviction via `asyncio`-compatible dict.

## Notes

- PyPI distribution name: `relintio-agent`
- Import path: `relintio_agent` (recommended)
- Legacy import path still supported: `ultimateprotector_agent`


## Options

- `license_key` (required)
- `api_url` (required) e.g. `https://api.relintio.com/v1`
- `sync_interval_seconds` (default: `10`; jitter and failure backoff are automatic)
- `allow_sample_rate` (default: `0.01`)
- `only_paths`: list[str] exact (`/checkout`) or prefix (`/product/*`)
- `except_paths`: list[str]
- `only_regex`: str (Python regex)

## Geo Enrichment

When CDN geo headers (`CF-IPCountry`, etc.) are absent, the agent calls the canonical `/v1/agent/geo-lookup` endpoint on `api.relintio.com`.
The server resolves the country using **local MaxMind GeoLite2 databases** — zero external API calls, zero cost, microsecond latency.
Results are cached in-memory (24h TTL) to minimize round-trips.

## Changelog

### 0.9.3

- **Import path alignment** - `relintio_agent` is now the documented import path, with `ultimateprotector_agent` kept as a compatibility alias.
- **Version telemetry alignment** - Runtime telemetry now reports `0.9.3`, matching the PyPI package version and release tag.

### 0.5.0

- **Additive risk-scoring engine** — 0-100 signal-based scoring with 7 weighted signals.
- **5-tier graduated response** — ALLOW, SLOW (`asyncio.sleep(2.0)`), CHALLENGE, DECOY, BLOCK.
- **Token-bucket rate limiter** — Replaces fixed-window counter. 8 tokens/sec, 24 burst, route-aware multipliers.
- **`risk_score` telemetry** — Agent-calculated score forwarded to server in log payload.

### 0.3.0

- **Geo enrichment architecture hardened** — The canonical `/v1/agent/geo-lookup` endpoint now performs local MaxMind GeoLite2 lookups instead of proxying to `ipinfo.io`. Agent behaviour is unchanged; the improvement is server-side.

### 0.2.0

- **HMAC payload verification** — Rules payloads are now authenticated with HMAC-SHA256 before decryption. Requires platform ≥ 2026-04.
- **`X-Agent-Version` header** — Sent on every `/verify` request for dashboard version tracking.
- **`outdated` status handling** — If the cloud responds with `outdated`, the agent fails open and stops protecting until updated.

### 0.1.1

- Initial stable release with AES-256-CBC encrypted rules sync.

## Dashboard Deployment Workflow

1. Open **Dashboard → Deployment**, select **Python**, and choose FastAPI, Starlette, or ASGI.
2. Download the recommended package and register the middleware immediately after creating the ASGI application.
3. Restart the server, then open one public route handled by the middleware.
4. Enter that exact URL or public IP endpoint in Relintio and select **Verify target**.

The agent reports runtime kind `python` and its version on synchronization and heartbeat requests. Configuration revisions are received automatically.
