Skip to content

Commit 73089d6

Browse files
committed
refactor: move payments and the firewall recommender behind subpaths
The root bundle had grown from 9,643 to 22,497 bytes — undoing most of the 65% reduction in #21 — because payments, gateway, entitlement and firewall all exported from the package root. Every consumer paid for them whether or not they charged anyone, and the firewall recommender in particular is an offline analysis tool that will never execute in middleware. dist/index.js 22,497 -> 11,608 B (8,695 -> 4,546 gzipped) dist/pay.js 10,861 B opt-in dist/firewall.js 6,821 B opt-in Entry points now: @apideck/agent-analytics detection, classification, agentPolicy, trackVisit @apideck/agent-analytics/verify Web Bot Auth + published IP range tables @apideck/agent-analytics/payments 402 challenges, gateways, entitlements @apideck/agent-analytics/firewall WAF recommendations (offline) @apideck/agent-analytics/markdown Markdown-twin negotiation agentPolicy stays in the root: classification without a policy to apply it to is half a library, and it costs ~2 kB. That is why the root lands at 11.6 kB rather than back at 9.6 kB. README gains an entry-point table with the real numbers, and every import example in the README, the testing guide and the site now points at the right subpath. Verified from a clean install of the packed package that all five entry points resolve. Found while pulling accurate figures for the site's install section, which was still advertising "216 tests" and "CI on Node 18, 20 and 22" — Node 18 was dropped in 0.12 for lacking globalThis.crypto, so the site was claiming support for a runtime the library refuses to run on. Both corrected.
1 parent 30a7782 commit 73089d6

6 files changed

Lines changed: 62 additions & 32 deletions

File tree

README.md

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ extra steps.
104104
So start by counting:
105105

106106
```ts
107-
import { paymentGate } from '@apideck/agent-analytics'
107+
import { paymentGate } from '@apideck/agent-analytics/payments'
108108
import { combinedVerifier } from '@apideck/agent-analytics/verify'
109109

110110
const gate = await paymentGate(req, {
@@ -125,7 +125,7 @@ When you know the number, switch to an entitlement: one 402 advertising a bulk
125125
offer, one settlement, a reusable credential.
126126

127127
```ts
128-
import { entitlementGateway } from '@apideck/agent-analytics'
128+
import { entitlementGateway } from '@apideck/agent-analytics/payments'
129129

130130
const gate = await paymentGate(req, {
131131
onTraining: 'charge',
@@ -258,7 +258,7 @@ every rule comes out in `log` mode and Vercel stages rule changes as drafts, so
258258
nothing is live until you run `vercel firewall publish` yourself.
259259

260260
```ts
261-
import { recommendFirewallRules, firewallScript } from '@apideck/agent-analytics'
261+
import { recommendFirewallRules, firewallScript } from '@apideck/agent-analytics/firewall'
262262

263263
const rules = recommendFirewallRules(observations) // aggregate from your warehouse
264264
console.log(firewallScript(rules)) // runnable, commented bash
@@ -282,6 +282,24 @@ privacy relays egress from hosting networks.
282282
See [`docs/TESTING-PAYMENTS.md`](./docs/TESTING-PAYMENTS.md) for testing the
283283
payment path end to end.
284284

285+
## Entry points
286+
287+
The root carries detection, classification, policy and capture — what every
288+
consumer needs. Everything optional lives behind a subpath, so it only reaches
289+
your bundle if you import it.
290+
291+
| Import | Contains | Root bundle cost |
292+
| --- | --- | ---: |
293+
| `@apideck/agent-analytics` | detection, classification, `agentPolicy`, `trackVisit` | 11.6 kB / **4.5 kB gz** |
294+
| `…/verify` | Web Bot Auth + published IP range tables | 19.0 kB |
295+
| `…/payments` | 402 challenges, gateways, entitlements | 10.9 kB |
296+
| `…/firewall` | WAF rule recommendations (offline tool) | 6.8 kB |
297+
| `…/markdown` | Markdown-twin content negotiation | 2.0 kB |
298+
299+
This split is load-bearing rather than tidy-minded. Exporting the payment and
300+
firewall surfaces from the root once pushed it from 9.6 kB to 22.5 kB — every
301+
site paid for a firewall recommender that will never run in middleware.
302+
285303
## Install
286304

287305
```bash

docs/TESTING-PAYMENTS.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ npm i @apideck/agent-analytics
2121

2222
```js
2323
// pay.mjs
24-
import { paymentGate, entitlementGateway, memoryEntitlementStore } from '@apideck/agent-analytics'
24+
import { paymentGate, entitlementGateway, memoryEntitlementStore } from '@apideck/agent-analytics/payments'
2525
import { combinedVerifier } from '@apideck/agent-analytics/verify'
2626

2727
const store = memoryEntitlementStore({ lic_abc: { id: 'lic_abc', remaining: 3 } })
@@ -72,7 +72,7 @@ prove:** that any real agent understands the challenge.
7272
### Inspect the challenge
7373
7474
```js
75-
import { paymentRequired } from '@apideck/agent-analytics'
75+
import { paymentRequired } from '@apideck/agent-analytics/payments'
7676

7777
const res = paymentRequired({
7878
challenges: [
@@ -101,7 +101,7 @@ Wire the gate into middleware, then drive it with user agents.
101101
```ts
102102
// middleware.ts
103103
import { NextResponse, type NextRequest } from 'next/server'
104-
import { paymentGate, entitlementGateway } from '@apideck/agent-analytics'
104+
import { paymentGate, entitlementGateway } from '@apideck/agent-analytics/payments'
105105
import { combinedVerifier } from '@apideck/agent-analytics/verify'
106106

107107
const gateway = entitlementGateway({
@@ -206,7 +206,7 @@ Stripe's SDK generates challenges and settles; wrap it rather than
206206
reimplementing.
207207
208208
```ts
209-
import { mppxGateway } from '@apideck/agent-analytics'
209+
import { mppxGateway } from '@apideck/agent-analytics/payments'
210210

211211
const mppx = Mppx.create({ methods: [...], secretKey })
212212
const handler = Mppx.compose(

package.json

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "@apideck/agent-analytics",
33
"version": "0.15.0",
4-
"description": "Track AI agent and bot traffic to your Next.js / Vercel app PostHog, webhooks, or any custom analytics backend. Detects Claude, ChatGPT, Perplexity, Google-Extended, and more.",
4+
"description": "Track AI agent and bot traffic to your Next.js / Vercel app \u2014 PostHog, webhooks, or any custom analytics backend. Detects Claude, ChatGPT, Perplexity, Google-Extended, and more.",
55
"keywords": [
66
"ai",
77
"agents",
@@ -43,6 +43,16 @@
4343
"import": "./dist/verify.js",
4444
"require": "./dist/verify.cjs"
4545
},
46+
"./payments": {
47+
"types": "./dist/pay.d.ts",
48+
"import": "./dist/pay.js",
49+
"require": "./dist/pay.cjs"
50+
},
51+
"./firewall": {
52+
"types": "./dist/firewall.d.ts",
53+
"import": "./dist/firewall.js",
54+
"require": "./dist/firewall.cjs"
55+
},
4656
"./posthog": {
4757
"types": "./dist/adapters/posthog.d.ts",
4858
"import": "./dist/adapters/posthog.js",

src/index.ts

Lines changed: 10 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,13 @@
1+
/**
2+
* Package root: detection, classification, policy and capture.
3+
*
4+
* Deliberately excludes the paid-access surface and the firewall recommender.
5+
* Both are opt-in and neither belongs in an edge bundle by default:
6+
*
7+
* @apideck/agent-analytics/verify identity verification + IP ranges
8+
* @apideck/agent-analytics/payments 402 challenges, gateways, entitlements
9+
* @apideck/agent-analytics/firewall WAF rule recommendations (offline)
10+
*/
111
export { trackVisit } from './track.js'
212
export {
313
AI_BOT_PATTERN,
@@ -14,23 +24,6 @@ export type { AgentClassification, AgentKind, HeadlessDetection } from './bots.j
1424
export { hashId, randomSecret, HashSecretError } from './hash.js'
1525
export { CaptureTransportError } from './errors.js'
1626
export { agentIntent, agentPolicy } from './policy.js'
17-
export { mppxGateway, paymentGate, x402Gateway } from './gateway.js'
18-
export { entitlementGateway, memoryEntitlementStore } from './entitlement.js'
19-
export { firewallScript, recommendFirewallRules } from './firewall.js'
20-
export type {
21-
FirewallAction,
22-
FirewallCondition,
23-
FirewallRecommendation,
24-
RateLimitSpec,
25-
RecommendOptions,
26-
TrafficObservation
27-
} from './firewall.js'
28-
export type {
29-
BulkOffer,
30-
Entitlement,
31-
EntitlementGatewayOptions,
32-
EntitlementStore
33-
} from './entitlement.js'
3427
export type {
3528
GatewayResult,
3629
Meter,
@@ -40,13 +33,6 @@ export type {
4033
PaymentGateway,
4134
X402GatewayOptions
4235
} from './gateway.js'
43-
export {
44-
hasPaymentPayload,
45-
paymentPayload,
46-
paymentRequired,
47-
respondToDecision,
48-
withSettlement
49-
} from './payments.js'
5036
export type {
5137
MppChallenge,
5238
PaymentChallenge,

src/pay.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
/**
2+
* Paid-access entry point. **EXPERIMENTAL** — see `payments.ts`.
3+
*
4+
* Kept out of the package root deliberately. Charging is opt-in and rare;
5+
* classification is what every consumer needs. Exporting these from the root
6+
* put the challenge builders, the gateway and the entitlement store into every
7+
* edge bundle whether or not the site ever charged anyone — the root grew from
8+
* 9.6 kB to 22.5 kB before anyone noticed.
9+
*
10+
* import { paymentGate } from '@apideck/agent-analytics/payments'
11+
*/
12+
export * from './payments.js'
13+
export * from './gateway.js'
14+
export * from './entitlement.js'

tsup.config.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ export default defineConfig({
55
'src/index.ts',
66
'src/markdown.ts',
77
'src/verify.ts',
8+
'src/pay.ts',
9+
'src/firewall.ts',
810
'src/adapters/posthog.ts',
911
'src/adapters/webhook.ts'
1012
],

0 commit comments

Comments
 (0)