You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
- Normalize path: unquote encoding, collapse . and .., cap length 2048
- Only numeric prices in price_by_route; invalid fallback to 1000
- Max 256 route entries; non-numeric and excess entries ignored
- Docs: PUBLISHER_GUIDE, README Security, CONCEPTS, DEVELOPMENT
-**`FAIRFETCH_TEST_MODE=true`** (default): CORS allows all origins (`*`); wallet ledger pre-seeds `wallet_test_agent_alpha` and `wallet_test_agent_beta`; mock payment tokens accepted.
192
192
-**`FAIRFETCH_TEST_MODE=false`**: CORS is restricted to `https://{FAIRFETCH_PUBLISHER_DOMAIN}`; no pre-seeded wallets; use real payment integration.
193
193
194
-
Optional **`FAIRFETCH_PRICE_BY_ROUTE`** (JSON map of path prefix → price) enables variable pricing by content URL path; see[Publisher Guide](docs/PUBLISHER_GUIDE.md) and [README Configuration](README.md#-configuration).
194
+
Optional **`FAIRFETCH_PRICE_BY_ROUTE`** (JSON map of path prefix → price) enables variable pricing by content URL path. Prices must be numeric; path is normalized for matching; up to 256 entries. See[Publisher Guide](docs/PUBLISHER_GUIDE.md) and [README Configuration](README.md#-configuration).
Copy file name to clipboardExpand all lines: README.md
+1Lines changed: 1 addition & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -697,6 +697,7 @@ fairfetch/
697
697
## 🔒 Security
698
698
699
699
-**URL validation:** The `url` parameter is validated before any outbound request. Private IPs (e.g. `127.0.0.1`, `10.x`, `192.168.x`), cloud metadata endpoints (e.g. `169.254.169.254`), and non-HTTP(S) schemes are rejected with `400` and `error: "url_blocked"`. This prevents SSRF (server-side request forgery).
700
+
-**Route-based pricing:** The content URL path used for price lookup is normalized (percent-encoding decoded, `.` and `..` segments collapsed) so clients cannot bypass route matching to get a different price. Only numeric prices are accepted; invalid route or default prices fall back safely.
700
701
-**Test mode:** With `FAIRFETCH_TEST_MODE=false`, CORS allows only `https://{FAIRFETCH_PUBLISHER_DOMAIN}` and the ledger does not pre-seed test wallets. Use test mode only for local development.
701
702
-**Error responses:** Upstream fetch and summarization errors return generic messages to clients; details are logged server-side only.
Copy file name to clipboardExpand all lines: docs/CONCEPTS.md
+2-2Lines changed: 2 additions & 2 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -264,7 +264,7 @@ what it costs. Here's what each field means:
264
264
|`compliance_level`| How strict the rules are for that tier. "standard" for light use, "strict" for training/commercial. |
265
265
|`available_tiers`| A menu of all options with prices, so your agent can pick the cheapest tier that fits its needs. |
266
266
267
-
**Variable pricing by route:** A publisher can configure different base prices for different URL paths (e.g. `FAIRFETCH_PRICE_BY_ROUTE` in the [Publisher Guide](PUBLISHER_GUIDE.md)). The 402 response for `?url=https://site.com/business` may show a different base price than `?url=https://site.com/sports`. Longest path prefix wins; the default price applies when no path matches.
267
+
**Variable pricing by route:** A publisher can configure different base prices for different URL paths (e.g. `FAIRFETCH_PRICE_BY_ROUTE` in the [Publisher Guide](PUBLISHER_GUIDE.md)). The 402 response for `?url=https://site.com/business` may show a different base price than `?url=https://site.com/sports`. Longest path prefix wins; the default price applies when no path matches. The path is normalized (encoding decoded, traversal collapsed) so route matching cannot be bypassed; only numeric prices are used.
268
268
269
269
---
270
270
@@ -293,7 +293,7 @@ The `Accept` header in your request tells Fairfetch what format you want:
293
293
|**USDC**| A stablecoin (cryptocurrency) pegged 1:1 to the US Dollar. Used for micro-payments because it has low transaction fees. |
294
294
|**Wallet (Pre-Funded)**| An account with a prepaid balance. AI agents include a wallet token in their requests, and the fee is deducted automatically — no 402 round-trip needed. Like an E-ZPass for content. |
295
295
|**Wallet Token**| A string (like `wallet_test_agent_alpha`) that identifies a pre-funded wallet. Include it in the `X-WALLET-TOKEN` header. |
296
-
|**Route-based pricing**| Optional publisher config (`FAIRFETCH_PRICE_BY_ROUTE`) that sets different base prices for different URL path prefixes (e.g. `/business` vs `/sports`). Longest matching path wins; the 402 quote reflects the base price for the requested content URL. |
296
+
|**Route-based pricing**| Optional publisher config (`FAIRFETCH_PRICE_BY_ROUTE`) that sets different base prices for different URL path prefixes (e.g. `/business` vs `/sports`). Longest matching path wins; the 402 quote reflects the base price for the requested content URL. Path is normalized and only numeric prices are accepted. |
297
297
|**x402**| A protocol that uses HTTP status code 402 to enable machine-to-machine payments. The server tells the client the price; the client pays and retries. |
298
298
|**Usage Grant**| A signed receipt proving an AI agent was authorized to use specific content for a specific purpose. |
299
299
|**Bot Steering**| The practice of redirecting web crawlers from scraping HTML to using the publisher's official API instead. |
Here, `/business` (and `/business/...`) is 2000, `/sports` is 500, and all other paths use the default 1000. Omit `FAIRFETCH_PRICE_BY_ROUTE` to use a single price for the whole site.
182
182
183
+
**Behavior and limits:** Prices must be numeric (digits only); non-numeric values are ignored. The content URL path is normalized (percent-encoding decoded, `.` and `..` segments collapsed) so route matching cannot be bypassed. At most 256 route entries are used; extra entries are ignored.
184
+
183
185
### 3.2 Generate a signing key (recommended for production)
184
186
185
187
This key lets AI agents (and you) verify that content really came from your server.
0 commit comments