@agentvisa/widget 0.2.2 → 0.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +110 -64
- package/dist/index.d.ts +0 -3
- package/dist/widget.esm.js +0 -3
- package/dist/widget.js +0 -3
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,16 +1,12 @@
|
|
|
1
1
|
# @agentvisa/widget
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Server-side middleware for **AgentVisa** verification — protect your Express or Next.js API routes so only AI agents backed by a verified human can access them.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
When an unverified agent hits a protected route, the middleware returns a `302` redirect (or `401`) pointing the agent to [agentvisa.ai/for-agents](https://agentvisa.ai/for-agents), where it prompts the human to sign up. Verified agents pass straight through.
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
-
|
|
10
|
-
- Unified response shape for all plans
|
|
11
|
-
- Zero runtime dependencies
|
|
12
|
-
- < 5KB gzipped
|
|
13
|
-
- TypeScript support
|
|
7
|
+
> **Which package should I use?**
|
|
8
|
+
> - **`@agentvisa/widget`** (this package) — use when you want the full viral redirect loop: unverified AI agents are redirected to AgentVisa to get verified, then come back. Also works as a plain `block` or `passthrough` gate. Supports Express and Next.js.
|
|
9
|
+
> - **[`@agentvisa/verify`](https://www.npmjs.com/package/@agentvisa/verify)** — use when you just want to verify a token and get a result back. Simpler API, no redirect, no growth loop. Works with any Node.js framework.
|
|
14
10
|
|
|
15
11
|
## Installation
|
|
16
12
|
|
|
@@ -18,77 +14,134 @@ Drop-in verification for websites that need to confirm a real human has approved
|
|
|
18
14
|
npm install @agentvisa/widget
|
|
19
15
|
```
|
|
20
16
|
|
|
21
|
-
|
|
17
|
+
## Quick start — Express
|
|
22
18
|
|
|
23
|
-
```
|
|
24
|
-
|
|
25
|
-
|
|
19
|
+
```ts
|
|
20
|
+
import express from 'express';
|
|
21
|
+
import { agentVisa } from '@agentvisa/widget/express';
|
|
26
22
|
|
|
27
|
-
|
|
23
|
+
const app = express();
|
|
28
24
|
|
|
29
|
-
|
|
25
|
+
app.use('/api', agentVisa({
|
|
26
|
+
widgetId: process.env.AV_WIDGET_ID!,
|
|
27
|
+
apiKey: process.env.AV_API_KEY!,
|
|
28
|
+
}));
|
|
29
|
+
|
|
30
|
+
app.post('/api/order', (req, res) => {
|
|
31
|
+
// Only reaches here if the agent is verified
|
|
32
|
+
console.log(req.agentVisa.result.plan); // "basic" | "pro"
|
|
33
|
+
res.json({ ok: true });
|
|
34
|
+
});
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Quick start — Next.js
|
|
30
38
|
|
|
31
39
|
```ts
|
|
32
|
-
|
|
40
|
+
// middleware.ts (project root)
|
|
41
|
+
import { withAgentVisa } from '@agentvisa/widget/next';
|
|
33
42
|
|
|
34
|
-
|
|
35
|
-
widgetId:
|
|
36
|
-
|
|
43
|
+
export default withAgentVisa({
|
|
44
|
+
widgetId: process.env.AV_WIDGET_ID!,
|
|
45
|
+
apiKey: process.env.AV_API_KEY!,
|
|
37
46
|
});
|
|
38
47
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
48
|
+
export const config = {
|
|
49
|
+
matcher: ['/api/:path*'],
|
|
50
|
+
};
|
|
42
51
|
```
|
|
43
52
|
|
|
44
|
-
|
|
53
|
+
## How agents send their token
|
|
54
|
+
|
|
55
|
+
Agents use the [AgentVisa MCP server](https://www.npmjs.com/package/@agentvisa/mcp) (`@agentvisa/mcp`) to exchange their permanent token for a short-lived `tmp_xxx` token, then send it in one of two ways:
|
|
56
|
+
|
|
57
|
+
**Standard mode:**
|
|
58
|
+
```
|
|
59
|
+
X-AgentVisa-Token: tmp_xxxxxxxxxxxxxxxxxxxx
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
**Web Bot Auth mode** (RFC 9421 — token bound in the signature):
|
|
63
|
+
```
|
|
64
|
+
AgentVisa-Assertion: tmp_xxxxxxxxxxxxxxxxxxxx
|
|
65
|
+
Signature-Input: sig1=("@method" "@path" "host" "agentvisa-assertion");keyid="key-1";created=1234567890
|
|
66
|
+
Signature: sig1=:base64sig:
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## Options
|
|
70
|
+
|
|
71
|
+
| Option | Type | Default | Description |
|
|
72
|
+
|--------|------|---------|-------------|
|
|
73
|
+
| `widgetId` | `string` | **required** | Your `wgt_xxx` widget ID |
|
|
74
|
+
| `apiKey` | `string` | **required** | Your `wk_xxx` API key — **server-side only** |
|
|
75
|
+
| `onUnverified` | `'redirect' \| 'block' \| 'passthrough'` | `'redirect'` | What to do when an agent is unverified |
|
|
76
|
+
| `redirectUrl` | `string` | `'https://agentvisa.ai/for-agents'` | Where to redirect unverified AI agents |
|
|
77
|
+
| `timeoutMs` | `number` | `5000` | Timeout for the `/v1/verify` API call |
|
|
78
|
+
|
|
79
|
+
### `onUnverified` modes
|
|
80
|
+
|
|
81
|
+
- **`'redirect'`** (default) — AI agents get a `302` to `/for-agents` with instructions. Human browsers and bot scrapers get a plain `401`. This is the viral growth mode: unverified agents send their human to sign up, then come back verified.
|
|
82
|
+
- **`'block'`** — All unverified requests get `401`. Quiet hard gate.
|
|
83
|
+
- **`'passthrough'`** — Attach the result to `req.agentVisa` (Express) or response headers (Next.js) and continue. Use this for soft-gating or analytics.
|
|
84
|
+
|
|
85
|
+
## Express — reading the result
|
|
86
|
+
|
|
87
|
+
On verified requests, `req.agentVisa` is populated:
|
|
45
88
|
|
|
46
89
|
```ts
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
90
|
+
app.post('/api/action', (req, res) => {
|
|
91
|
+
const av = req.agentVisa!;
|
|
92
|
+
console.log(av.verified); // true
|
|
93
|
+
console.log(av.result.plan); // "basic" | "pro"
|
|
94
|
+
console.log(av.result.valid); // true
|
|
95
|
+
console.log(av.result.verified_at); // ISO timestamp
|
|
96
|
+
console.log(av.result.web_bot_auth_bound); // true if RFC 9421 bound (Pro)
|
|
50
97
|
});
|
|
51
|
-
|
|
52
|
-
const result = await visa.verify();
|
|
53
98
|
```
|
|
54
99
|
|
|
55
|
-
|
|
100
|
+
In `'passthrough'` mode, unverified requests also reach your handler:
|
|
56
101
|
|
|
57
|
-
```
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
}
|
|
64
|
-
|
|
102
|
+
```ts
|
|
103
|
+
app.use(agentVisa({ widgetId, apiKey, onUnverified: 'passthrough' }));
|
|
104
|
+
|
|
105
|
+
app.get('/api/data', (req, res) => {
|
|
106
|
+
if (!req.agentVisa?.verified) {
|
|
107
|
+
return res.json({ data: publicData, premium: null });
|
|
108
|
+
}
|
|
109
|
+
res.json({ data: publicData, premium: premiumData });
|
|
110
|
+
});
|
|
65
111
|
```
|
|
66
112
|
|
|
67
|
-
##
|
|
113
|
+
## Next.js — reading the result
|
|
68
114
|
|
|
69
|
-
|
|
115
|
+
On the edge or in a route handler, read the forwarded headers:
|
|
116
|
+
|
|
117
|
+
```ts
|
|
118
|
+
// app/api/route.ts
|
|
119
|
+
export async function POST(request: Request) {
|
|
120
|
+
const verified = request.headers.get('x-agentvisa-verified') === 'true';
|
|
121
|
+
const reason = request.headers.get('x-agentvisa-reason');
|
|
122
|
+
|
|
123
|
+
if (!verified) {
|
|
124
|
+
return Response.json({ error: reason }, { status: 401 });
|
|
125
|
+
}
|
|
126
|
+
// Proceed
|
|
127
|
+
}
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
## Response shape from `/v1/verify`
|
|
70
131
|
|
|
71
132
|
```json
|
|
72
133
|
{
|
|
73
134
|
"valid": true,
|
|
74
135
|
"reason": "ok",
|
|
75
136
|
"plan": "basic",
|
|
76
|
-
"widget_id": "
|
|
77
|
-
"
|
|
78
|
-
"
|
|
79
|
-
"
|
|
80
|
-
"verified_at": null,
|
|
81
|
-
"expires_at": null
|
|
137
|
+
"widget_id": "wgt_abc123",
|
|
138
|
+
"verified_at": "2026-06-22T10:00:00Z",
|
|
139
|
+
"expires_at": "2026-06-23T10:00:00Z",
|
|
140
|
+
"domain_verified": true
|
|
82
141
|
}
|
|
83
142
|
```
|
|
84
143
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
| Option | Type | Default | Description |
|
|
88
|
-
|--------------|--------------------|--------------------------|---------------------------------|
|
|
89
|
-
| `widgetId` | `string` | **required** | Your AgentVisa widget ID |
|
|
90
|
-
| `plan` | `"basic" \| "pro"` | `"basic"` | Verification tier |
|
|
91
|
-
| `apiBaseUrl` | `string` | `"https://api.agentvisa.ai"` | Backend API base URL |
|
|
144
|
+
Pro plan additionally returns `age_over_18`, `age_over_21`, `multiple_agents_authorized`, `web_bot_auth_bound`, and AVS-style attribute confirmations. Raw PII (name, email, phone) is never returned.
|
|
92
145
|
|
|
93
146
|
## Development
|
|
94
147
|
|
|
@@ -98,17 +151,10 @@ npm run build
|
|
|
98
151
|
```
|
|
99
152
|
|
|
100
153
|
Build output is in `dist/`:
|
|
101
|
-
|
|
102
|
-
- `
|
|
103
|
-
- `
|
|
104
|
-
-
|
|
105
|
-
|
|
106
|
-
## Examples
|
|
107
|
-
|
|
108
|
-
See the `examples/` folder:
|
|
109
|
-
|
|
110
|
-
- `basic.html` — Basic tier demo
|
|
111
|
-
- `pro.html` — Pro tier demo with richer data
|
|
154
|
+
- `dist/express/index.js` — Express middleware
|
|
155
|
+
- `dist/next/index.js` — Next.js middleware
|
|
156
|
+
- `dist/core.js` — Shared verification logic
|
|
157
|
+
- TypeScript declarations alongside each `.js` file
|
|
112
158
|
|
|
113
159
|
## Contributing
|
|
114
160
|
|
|
@@ -120,4 +166,4 @@ See [SECURITY.md](SECURITY.md).
|
|
|
120
166
|
|
|
121
167
|
## License
|
|
122
168
|
|
|
123
|
-
MIT © [AgentVisa](https://agentvisa.ai)
|
|
169
|
+
MIT © [AgentVisa](https://agentvisa.ai)
|
package/dist/index.d.ts
CHANGED
|
@@ -22,9 +22,6 @@ interface VerificationResult {
|
|
|
22
22
|
verified_at: string | null;
|
|
23
23
|
expires_at: string | null;
|
|
24
24
|
domain_verified?: boolean;
|
|
25
|
-
human_name?: string | null;
|
|
26
|
-
email?: string | null;
|
|
27
|
-
phone?: string | null;
|
|
28
25
|
age_over_18?: "y" | "n" | "null";
|
|
29
26
|
age_over_21?: "y" | "n" | "null";
|
|
30
27
|
gov_id_pic_validation?: "y" | "n" | "null";
|
package/dist/widget.esm.js
CHANGED
package/dist/widget.js
CHANGED