wiki-formant 0.27.1 → 0.29.0
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 +106 -31
- package/bin/analytics-digest.mjs +57 -0
- package/dist/analytics.d.ts +166 -26
- package/dist/analytics.js +267 -47
- package/dist/blocks.d.ts +139 -0
- package/dist/blocks.js +68 -0
- package/dist/db.d.ts +21 -0
- package/dist/db.js +27 -0
- package/dist/dom.d.ts +15 -0
- package/dist/dom.js +57 -0
- package/dist/feed.d.ts +0 -1
- package/dist/feed.js +1 -1
- package/dist/freshness.d.ts +6 -1
- package/dist/freshness.js +7 -3
- package/dist/http.d.ts +10 -0
- package/dist/http.js +13 -0
- package/dist/link-check.d.ts +0 -24
- package/dist/link-check.js +3 -3
- package/dist/mcp.d.ts +6 -5
- package/dist/mcp.js +4 -3
- package/dist/rate-limit.d.ts +28 -2
- package/dist/rate-limit.js +55 -3
- package/dist/react.d.ts +7 -0
- package/dist/react.js +9 -1
- package/dist/validation.d.ts +29 -0
- package/dist/validation.js +51 -0
- package/package.json +12 -25
- package/dist/index.d.ts +0 -22
- package/dist/index.js +0 -27
- package/dist/rola.d.ts +0 -127
- package/dist/rola.js +0 -150
- package/dist/x402.d.ts +0 -95
- package/dist/x402.js +0 -212
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "wiki-formant",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.29.0",
|
|
4
4
|
"description": "The portable half of a wiki: derived taxonomy and facet controls, a version-negotiating MCP transport, markdown twins, block rendering, a rich-text editor engine, and conditional-GET plumbing.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -22,10 +22,6 @@
|
|
|
22
22
|
"*.css"
|
|
23
23
|
],
|
|
24
24
|
"exports": {
|
|
25
|
-
".": {
|
|
26
|
-
"types": "./dist/index.d.ts",
|
|
27
|
-
"import": "./dist/index.js"
|
|
28
|
-
},
|
|
29
25
|
"./taxonomy": {
|
|
30
26
|
"types": "./dist/taxonomy.d.ts",
|
|
31
27
|
"import": "./dist/taxonomy.js"
|
|
@@ -58,6 +54,10 @@
|
|
|
58
54
|
"types": "./dist/rate-limit.d.ts",
|
|
59
55
|
"import": "./dist/rate-limit.js"
|
|
60
56
|
},
|
|
57
|
+
"./db": {
|
|
58
|
+
"types": "./dist/db.d.ts",
|
|
59
|
+
"import": "./dist/db.js"
|
|
60
|
+
},
|
|
61
61
|
"./analytics": {
|
|
62
62
|
"types": "./dist/analytics.d.ts",
|
|
63
63
|
"import": "./dist/analytics.js"
|
|
@@ -142,14 +142,6 @@
|
|
|
142
142
|
"types": "./dist/tiptap.d.ts",
|
|
143
143
|
"import": "./dist/tiptap.js"
|
|
144
144
|
},
|
|
145
|
-
"./rola": {
|
|
146
|
-
"types": "./dist/rola.d.ts",
|
|
147
|
-
"import": "./dist/rola.js"
|
|
148
|
-
},
|
|
149
|
-
"./x402": {
|
|
150
|
-
"types": "./dist/x402.d.ts",
|
|
151
|
-
"import": "./dist/x402.js"
|
|
152
|
-
},
|
|
153
145
|
"./base.css": "./dist/base.css",
|
|
154
146
|
"./block-views": {
|
|
155
147
|
"types": "./dist/block-views.d.ts",
|
|
@@ -182,7 +174,8 @@
|
|
|
182
174
|
},
|
|
183
175
|
"bin": {
|
|
184
176
|
"check-classes": "bin/check-classes.mjs",
|
|
185
|
-
"check-pages": "bin/check-pages.mjs"
|
|
177
|
+
"check-pages": "bin/check-pages.mjs",
|
|
178
|
+
"analytics-digest": "bin/analytics-digest.mjs"
|
|
186
179
|
},
|
|
187
180
|
"files": [
|
|
188
181
|
"dist",
|
|
@@ -197,7 +190,6 @@
|
|
|
197
190
|
"prepare": "git config core.hooksPath .githooks || true"
|
|
198
191
|
},
|
|
199
192
|
"devDependencies": {
|
|
200
|
-
"@radixdlt/rola": "^2.1.0",
|
|
201
193
|
"@tiptap/core": "^2.10.0",
|
|
202
194
|
"@tiptap/extension-code-block": "^2.10.0",
|
|
203
195
|
"@tiptap/extension-image": "^2.27.3",
|
|
@@ -215,14 +207,12 @@
|
|
|
215
207
|
"@types/react": "^19.0.0",
|
|
216
208
|
"@types/sanitize-html": "^2.16.1",
|
|
217
209
|
"fast-diff": "^1.3.0",
|
|
218
|
-
"jose": "^6.2.10",
|
|
219
210
|
"jsdom": "^30.1.0",
|
|
220
211
|
"react": "^19.2.4",
|
|
221
212
|
"sanitize-html": "^2.17.7",
|
|
222
213
|
"typescript": "^5.9.0"
|
|
223
214
|
},
|
|
224
215
|
"peerDependencies": {
|
|
225
|
-
"@radixdlt/rola": ">=2",
|
|
226
216
|
"@tiptap/core": ">=2.10",
|
|
227
217
|
"@tiptap/extension-code-block": ">=2.10",
|
|
228
218
|
"@tiptap/extension-image": ">=2.10",
|
|
@@ -237,9 +227,9 @@
|
|
|
237
227
|
"@tiptap/react": ">=2.10",
|
|
238
228
|
"@tiptap/starter-kit": ">=2.10",
|
|
239
229
|
"fast-diff": ">=1.3",
|
|
240
|
-
"jose": ">=5",
|
|
241
230
|
"react": ">=18",
|
|
242
|
-
"sanitize-html": ">=2"
|
|
231
|
+
"sanitize-html": ">=2",
|
|
232
|
+
"pg": ">=8"
|
|
243
233
|
},
|
|
244
234
|
"peerDependenciesMeta": {
|
|
245
235
|
"react": {
|
|
@@ -257,12 +247,6 @@
|
|
|
257
247
|
"@tiptap/extension-code-block": {
|
|
258
248
|
"optional": true
|
|
259
249
|
},
|
|
260
|
-
"jose": {
|
|
261
|
-
"optional": true
|
|
262
|
-
},
|
|
263
|
-
"@radixdlt/rola": {
|
|
264
|
-
"optional": true
|
|
265
|
-
},
|
|
266
250
|
"@tiptap/starter-kit": {
|
|
267
251
|
"optional": true
|
|
268
252
|
},
|
|
@@ -295,6 +279,9 @@
|
|
|
295
279
|
},
|
|
296
280
|
"fast-diff": {
|
|
297
281
|
"optional": true
|
|
282
|
+
},
|
|
283
|
+
"pg": {
|
|
284
|
+
"optional": true
|
|
298
285
|
}
|
|
299
286
|
}
|
|
300
287
|
}
|
package/dist/index.d.ts
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
export * from './taxonomy.js';
|
|
2
|
-
export * from './mcp.js';
|
|
3
|
-
export * from './headings.js';
|
|
4
|
-
export * from './links.js';
|
|
5
|
-
export * from './markdown.js';
|
|
6
|
-
export * from './markdown.js';
|
|
7
|
-
export * from './http.js';
|
|
8
|
-
export * from './pagination.js';
|
|
9
|
-
export * from './versioning.js';
|
|
10
|
-
export * from './rate-limit.js';
|
|
11
|
-
export * from './analytics.js';
|
|
12
|
-
export * from './blocks.js';
|
|
13
|
-
export * from './text.js';
|
|
14
|
-
export * from './maps.js';
|
|
15
|
-
export * from './freshness.js';
|
|
16
|
-
export * from './combobox.js';
|
|
17
|
-
export * from './crawlers.js';
|
|
18
|
-
export * from './revisions.js';
|
|
19
|
-
export * from './feed.js';
|
|
20
|
-
export * from './license.js';
|
|
21
|
-
export * from './seeded.js';
|
|
22
|
-
export * from './metadata.js';
|
package/dist/index.js
DELETED
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
// wiki-formant — the portable half of a wiki.
|
|
2
|
-
//
|
|
3
|
-
// Nothing here touches a database, a framework or a design system. Those are
|
|
4
|
-
// the parts every wiki must own; these are the parts every wiki rebuilds and
|
|
5
|
-
// then lets drift.
|
|
6
|
-
export * from './taxonomy.js';
|
|
7
|
-
export * from './mcp.js';
|
|
8
|
-
export * from './headings.js';
|
|
9
|
-
export * from './links.js';
|
|
10
|
-
export * from './markdown.js';
|
|
11
|
-
export * from './markdown.js';
|
|
12
|
-
export * from './http.js';
|
|
13
|
-
export * from './pagination.js';
|
|
14
|
-
export * from './versioning.js';
|
|
15
|
-
export * from './rate-limit.js';
|
|
16
|
-
export * from './analytics.js';
|
|
17
|
-
export * from './blocks.js';
|
|
18
|
-
export * from './text.js';
|
|
19
|
-
export * from './maps.js';
|
|
20
|
-
export * from './freshness.js';
|
|
21
|
-
export * from './combobox.js';
|
|
22
|
-
export * from './crawlers.js';
|
|
23
|
-
export * from './revisions.js';
|
|
24
|
-
export * from './feed.js';
|
|
25
|
-
export * from './license.js';
|
|
26
|
-
export * from './seeded.js';
|
|
27
|
-
export * from './metadata.js';
|
package/dist/rola.d.ts
DELETED
|
@@ -1,127 +0,0 @@
|
|
|
1
|
-
export interface AuthSession {
|
|
2
|
-
userId: string;
|
|
3
|
-
radixAddress: string;
|
|
4
|
-
personaAddress?: string;
|
|
5
|
-
displayName?: string;
|
|
6
|
-
expiresAt: Date;
|
|
7
|
-
}
|
|
8
|
-
export interface SignedChallenge {
|
|
9
|
-
challenge: string;
|
|
10
|
-
address: string;
|
|
11
|
-
proof: {
|
|
12
|
-
publicKey: string;
|
|
13
|
-
signature: string;
|
|
14
|
-
curve: 'curve25519' | 'secp256k1';
|
|
15
|
-
};
|
|
16
|
-
}
|
|
17
|
-
/**
|
|
18
|
-
* The two Prisma delegates this needs, structurally. Both wikis' `Session` and
|
|
19
|
-
* `Challenge` models already satisfy it, so the binding is
|
|
20
|
-
* `{ session: prisma.session, challenge: prisma.challenge }`.
|
|
21
|
-
*/
|
|
22
|
-
export interface RolaStore {
|
|
23
|
-
session: {
|
|
24
|
-
create(args: {
|
|
25
|
-
data: {
|
|
26
|
-
userId: string;
|
|
27
|
-
token: string;
|
|
28
|
-
expiresAt: Date;
|
|
29
|
-
};
|
|
30
|
-
}): Promise<unknown>;
|
|
31
|
-
findUnique(args: {
|
|
32
|
-
where: {
|
|
33
|
-
token: string;
|
|
34
|
-
};
|
|
35
|
-
}): Promise<{
|
|
36
|
-
id: string;
|
|
37
|
-
expiresAt: Date;
|
|
38
|
-
} | null>;
|
|
39
|
-
delete(args: {
|
|
40
|
-
where: {
|
|
41
|
-
id: string;
|
|
42
|
-
};
|
|
43
|
-
}): Promise<unknown>;
|
|
44
|
-
deleteMany(args: {
|
|
45
|
-
where: {
|
|
46
|
-
token: string;
|
|
47
|
-
};
|
|
48
|
-
}): Promise<unknown>;
|
|
49
|
-
};
|
|
50
|
-
challenge: {
|
|
51
|
-
create(args: {
|
|
52
|
-
data: {
|
|
53
|
-
challenge: string;
|
|
54
|
-
expiresAt: Date;
|
|
55
|
-
};
|
|
56
|
-
}): Promise<unknown>;
|
|
57
|
-
findUnique(args: {
|
|
58
|
-
where: {
|
|
59
|
-
challenge: string;
|
|
60
|
-
};
|
|
61
|
-
}): Promise<{
|
|
62
|
-
id: string;
|
|
63
|
-
expiresAt: Date;
|
|
64
|
-
} | null>;
|
|
65
|
-
delete(args: {
|
|
66
|
-
where: {
|
|
67
|
-
id: string;
|
|
68
|
-
};
|
|
69
|
-
}): Promise<unknown>;
|
|
70
|
-
};
|
|
71
|
-
}
|
|
72
|
-
/** What `await cookies()` already gives you, narrowed to what this uses. */
|
|
73
|
-
export interface CookieJar {
|
|
74
|
-
get(name: string): {
|
|
75
|
-
value: string;
|
|
76
|
-
} | undefined;
|
|
77
|
-
set(name: string, value: string, options: {
|
|
78
|
-
httpOnly: boolean;
|
|
79
|
-
secure: boolean;
|
|
80
|
-
sameSite: 'lax';
|
|
81
|
-
expires: Date;
|
|
82
|
-
path: string;
|
|
83
|
-
}): void;
|
|
84
|
-
delete(name: string): void;
|
|
85
|
-
}
|
|
86
|
-
export interface RolaAuthConfig {
|
|
87
|
-
/** This wiki's session cookie. The one thing the two copies actually differed in. */
|
|
88
|
-
cookieName: string;
|
|
89
|
-
jwtSecret: Uint8Array;
|
|
90
|
-
store: RolaStore;
|
|
91
|
-
cookies: () => Promise<CookieJar>;
|
|
92
|
-
rola: {
|
|
93
|
-
expectedOrigin: string;
|
|
94
|
-
dAppDefinitionAddress: string;
|
|
95
|
-
networkId: number;
|
|
96
|
-
applicationName: string;
|
|
97
|
-
};
|
|
98
|
-
sessionDurationMs?: number;
|
|
99
|
-
challengeTtlSec?: number;
|
|
100
|
-
/** Defaults to `process.env.NODE_ENV === 'production'`. */
|
|
101
|
-
secureCookies?: boolean;
|
|
102
|
-
}
|
|
103
|
-
/**
|
|
104
|
-
* A wallet address tells you which proof type it is, and getting it wrong is a
|
|
105
|
-
* silent rejection: the ROLA library verifies an `identity_*` proof only under
|
|
106
|
-
* `type: 'persona'`. One of the two copies this replaces hardcoded `'account'`
|
|
107
|
-
* and so could never accept a persona login at all.
|
|
108
|
-
*/
|
|
109
|
-
export declare function proofType(address: string): 'account' | 'persona' | null;
|
|
110
|
-
export interface RolaAuth {
|
|
111
|
-
createSession(userId: string, radixAddress: string, personaAddress?: string, displayName?: string): Promise<string>;
|
|
112
|
-
getSession(request?: {
|
|
113
|
-
headers: {
|
|
114
|
-
get(name: string): string | null;
|
|
115
|
-
};
|
|
116
|
-
}): Promise<AuthSession | null>;
|
|
117
|
-
destroySession(): Promise<void>;
|
|
118
|
-
generateChallenge(): Promise<{
|
|
119
|
-
challenge: string;
|
|
120
|
-
expiresAt: Date;
|
|
121
|
-
}>;
|
|
122
|
-
verifySignedChallenge(signed: SignedChallenge): Promise<{
|
|
123
|
-
isValid: boolean;
|
|
124
|
-
error?: string;
|
|
125
|
-
}>;
|
|
126
|
-
}
|
|
127
|
-
export declare function createRolaAuth(config: RolaAuthConfig): RolaAuth;
|
package/dist/rola.js
DELETED
|
@@ -1,150 +0,0 @@
|
|
|
1
|
-
// rola.ts — Radix On-Ledger Authentication: challenge, proof, session.
|
|
2
|
-
//
|
|
3
|
-
// Parameterised on the two things a second wiki would differ in: the cookie
|
|
4
|
-
// name and its dApp identity. It verifies persona (identity_*) proofs as well
|
|
5
|
-
// as account proofs, and logs a failed verification so it is diagnosable.
|
|
6
|
-
//
|
|
7
|
-
// **One consumer.** caper's wallet auth never used this stack and acuiq gates
|
|
8
|
-
// only its wiki editor, on a shared secret. Keep it — the
|
|
9
|
-
// persona-proof fix and the error logging are worth not losing, and the ports
|
|
10
|
-
// below are what make it reusable at all — but do not mistake it for a proven
|
|
11
|
-
// shared abstraction. It is radix-wiki's auth that happens to live in a package.
|
|
12
|
-
//
|
|
13
|
-
// Storage and cookies are ports rather than imports. A Prisma client is
|
|
14
|
-
// generated per repo and cannot be shared, and taking `next/headers` here would
|
|
15
|
-
// bind the package to a framework it otherwise knows nothing about. Both ports
|
|
16
|
-
// are shaped so the caller passes what it already has — the delegate and the
|
|
17
|
-
// cookie jar — with no adapter to write.
|
|
18
|
-
//
|
|
19
|
-
// `jose` and `@radixdlt/rola` are optional peers: only a repo importing this
|
|
20
|
-
// subpath needs them installed.
|
|
21
|
-
import { SignJWT, jwtVerify } from 'jose';
|
|
22
|
-
import { Rola } from '@radixdlt/rola';
|
|
23
|
-
const DEFAULT_SESSION_MS = 7 * 24 * 60 * 60 * 1000;
|
|
24
|
-
const DEFAULT_CHALLENGE_TTL_SEC = 300;
|
|
25
|
-
const bytesToHex = (bytes) => Array.from(bytes, b => b.toString(16).padStart(2, '0')).join('');
|
|
26
|
-
/**
|
|
27
|
-
* A wallet address tells you which proof type it is, and getting it wrong is a
|
|
28
|
-
* silent rejection: the ROLA library verifies an `identity_*` proof only under
|
|
29
|
-
* `type: 'persona'`. One of the two copies this replaces hardcoded `'account'`
|
|
30
|
-
* and so could never accept a persona login at all.
|
|
31
|
-
*/
|
|
32
|
-
export function proofType(address) {
|
|
33
|
-
if (address.startsWith('account_'))
|
|
34
|
-
return 'account';
|
|
35
|
-
if (address.startsWith('identity_'))
|
|
36
|
-
return 'persona';
|
|
37
|
-
return null;
|
|
38
|
-
}
|
|
39
|
-
export function createRolaAuth(config) {
|
|
40
|
-
const { cookieName, jwtSecret, store, cookies, sessionDurationMs = DEFAULT_SESSION_MS, challengeTtlSec = DEFAULT_CHALLENGE_TTL_SEC, secureCookies = process.env.NODE_ENV === 'production', } = config;
|
|
41
|
-
const rola = Rola(config.rola);
|
|
42
|
-
async function verifyToken(token) {
|
|
43
|
-
try {
|
|
44
|
-
const { payload } = await jwtVerify(token, jwtSecret);
|
|
45
|
-
const session = await store.session.findUnique({ where: { token } });
|
|
46
|
-
if (!session || session.expiresAt < new Date()) {
|
|
47
|
-
if (session)
|
|
48
|
-
await store.session.delete({ where: { id: session.id } }).catch(() => { });
|
|
49
|
-
return null;
|
|
50
|
-
}
|
|
51
|
-
return {
|
|
52
|
-
userId: payload.userId,
|
|
53
|
-
radixAddress: payload.radixAddress,
|
|
54
|
-
personaAddress: payload.personaAddress,
|
|
55
|
-
displayName: payload.displayName,
|
|
56
|
-
expiresAt: new Date(payload.exp * 1000),
|
|
57
|
-
};
|
|
58
|
-
}
|
|
59
|
-
catch {
|
|
60
|
-
return null;
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
/** Consumes the challenge: a replayed one must not verify twice. */
|
|
64
|
-
async function validateChallenge(challenge) {
|
|
65
|
-
const stored = await store.challenge.findUnique({ where: { challenge } });
|
|
66
|
-
if (!stored || stored.expiresAt < new Date()) {
|
|
67
|
-
if (stored)
|
|
68
|
-
await store.challenge.delete({ where: { id: stored.id } });
|
|
69
|
-
return false;
|
|
70
|
-
}
|
|
71
|
-
await store.challenge.delete({ where: { id: stored.id } });
|
|
72
|
-
return true;
|
|
73
|
-
}
|
|
74
|
-
return {
|
|
75
|
-
async createSession(userId, radixAddress, personaAddress, displayName) {
|
|
76
|
-
const expiresAt = new Date(Date.now() + sessionDurationMs);
|
|
77
|
-
const token = await new SignJWT({ userId, radixAddress, personaAddress, displayName })
|
|
78
|
-
.setProtectedHeader({ alg: 'HS256' })
|
|
79
|
-
.setIssuedAt()
|
|
80
|
-
.setExpirationTime(expiresAt)
|
|
81
|
-
.setJti(crypto.randomUUID())
|
|
82
|
-
.sign(jwtSecret);
|
|
83
|
-
await store.session.create({ data: { userId, token, expiresAt } });
|
|
84
|
-
const jar = await cookies();
|
|
85
|
-
jar.set(cookieName, token, {
|
|
86
|
-
httpOnly: true,
|
|
87
|
-
secure: secureCookies,
|
|
88
|
-
sameSite: 'lax',
|
|
89
|
-
expires: expiresAt,
|
|
90
|
-
path: '/',
|
|
91
|
-
});
|
|
92
|
-
return token;
|
|
93
|
-
},
|
|
94
|
-
async getSession(request) {
|
|
95
|
-
const jar = await cookies();
|
|
96
|
-
const cookieToken = jar.get(cookieName)?.value;
|
|
97
|
-
if (cookieToken) {
|
|
98
|
-
const session = await verifyToken(cookieToken);
|
|
99
|
-
if (session)
|
|
100
|
-
return session;
|
|
101
|
-
}
|
|
102
|
-
// Agents authenticate per-request with a Bearer token rather than a
|
|
103
|
-
// cookie, so the header is a second, equal route in — not a fallback.
|
|
104
|
-
if (request) {
|
|
105
|
-
const authHeader = request.headers.get('Authorization');
|
|
106
|
-
const bearerToken = authHeader?.startsWith('Bearer ') ? authHeader.slice(7) : null;
|
|
107
|
-
if (bearerToken)
|
|
108
|
-
return verifyToken(bearerToken);
|
|
109
|
-
}
|
|
110
|
-
return null;
|
|
111
|
-
},
|
|
112
|
-
async destroySession() {
|
|
113
|
-
const jar = await cookies();
|
|
114
|
-
const token = jar.get(cookieName)?.value;
|
|
115
|
-
if (token)
|
|
116
|
-
await store.session.deleteMany({ where: { token } });
|
|
117
|
-
jar.delete(cookieName);
|
|
118
|
-
},
|
|
119
|
-
async generateChallenge() {
|
|
120
|
-
const array = new Uint8Array(32);
|
|
121
|
-
crypto.getRandomValues(array);
|
|
122
|
-
const challenge = bytesToHex(array);
|
|
123
|
-
const expiresAt = new Date(Date.now() + challengeTtlSec * 1000);
|
|
124
|
-
await store.challenge.create({ data: { challenge, expiresAt } });
|
|
125
|
-
return { challenge, expiresAt };
|
|
126
|
-
},
|
|
127
|
-
async verifySignedChallenge(signedChallenge) {
|
|
128
|
-
try {
|
|
129
|
-
if (!(await validateChallenge(signedChallenge.challenge))) {
|
|
130
|
-
console.error('ROLA: challenge validation failed', signedChallenge.challenge.slice(0, 16) + '...');
|
|
131
|
-
return { isValid: false, error: 'Invalid or expired challenge' };
|
|
132
|
-
}
|
|
133
|
-
const type = proofType(signedChallenge.address);
|
|
134
|
-
if (!type) {
|
|
135
|
-
throw new Error(`ROLA: unrecognized address prefix (expected account_* or identity_*): ${signedChallenge.address}`);
|
|
136
|
-
}
|
|
137
|
-
const result = await rola.verifySignedChallenge({ ...signedChallenge, type });
|
|
138
|
-
if (result.isErr()) {
|
|
139
|
-
console.error('ROLA: verification failed', result.error.reason, result.error);
|
|
140
|
-
return { isValid: false, error: result.error.reason };
|
|
141
|
-
}
|
|
142
|
-
return { isValid: true };
|
|
143
|
-
}
|
|
144
|
-
catch (error) {
|
|
145
|
-
console.error('ROLA verification error:', error);
|
|
146
|
-
return { isValid: false, error: 'Verification failed' };
|
|
147
|
-
}
|
|
148
|
-
},
|
|
149
|
-
};
|
|
150
|
-
}
|
package/dist/x402.d.ts
DELETED
|
@@ -1,95 +0,0 @@
|
|
|
1
|
-
import type { EnvelopeGate, RpcRequest } from './mcp.js';
|
|
2
|
-
/**
|
|
3
|
-
* The slice of `@x402/core`'s `x402ResourceServer` this module calls.
|
|
4
|
-
*
|
|
5
|
-
* Method syntax, not properties: the real methods carry the library's own
|
|
6
|
-
* `PaymentPayload` / `PaymentRequirements` types, and bivariant method
|
|
7
|
-
* parameters are what lets a real server satisfy a port written in `unknown`.
|
|
8
|
-
*/
|
|
9
|
-
export interface X402ServerPort {
|
|
10
|
-
buildPaymentRequirements(spec: {
|
|
11
|
-
scheme: 'exact';
|
|
12
|
-
network: string;
|
|
13
|
-
payTo: string;
|
|
14
|
-
price: string;
|
|
15
|
-
maxTimeoutSeconds: number;
|
|
16
|
-
}): Promise<unknown>;
|
|
17
|
-
createPaymentRequiredResponse(accepts: unknown, resource: {
|
|
18
|
-
url: string;
|
|
19
|
-
description: string;
|
|
20
|
-
mimeType: string;
|
|
21
|
-
serviceName: string;
|
|
22
|
-
tags: string[];
|
|
23
|
-
}, error: string, extensions: unknown, context: unknown, payload?: unknown): Promise<unknown>;
|
|
24
|
-
findMatchingRequirements(accepts: unknown, payload: unknown): unknown;
|
|
25
|
-
verifyPayment(payload: unknown, requirements: unknown, extensions: unknown, context: unknown): Promise<{
|
|
26
|
-
isValid: boolean;
|
|
27
|
-
invalidReason?: string;
|
|
28
|
-
}>;
|
|
29
|
-
settlePayment(payload: unknown, requirements: unknown, extensions: unknown, context: unknown): Promise<{
|
|
30
|
-
success?: boolean;
|
|
31
|
-
}>;
|
|
32
|
-
}
|
|
33
|
-
/** One priced surface, as the caller describes it. All of this is policy. */
|
|
34
|
-
export interface PaidSurface {
|
|
35
|
-
/**
|
|
36
|
-
* Which envelope slot the challenge can travel in. A tool result carries
|
|
37
|
-
* `structuredContent`; a `resources/read` has no such shape and takes a
|
|
38
|
-
* JSON-RPC error instead.
|
|
39
|
-
*/
|
|
40
|
-
kind: 'tool' | 'resource';
|
|
41
|
-
/** Canonical URL of the thing being sold, for the 402 body and the catalogue. */
|
|
42
|
-
resource: string;
|
|
43
|
-
price: string;
|
|
44
|
-
mimeType: string;
|
|
45
|
-
description: string;
|
|
46
|
-
/** The sentence an unpaid caller reads. Say what else is free. */
|
|
47
|
-
unpaidMessage: string;
|
|
48
|
-
/**
|
|
49
|
-
* Bazaar's MCP discovery shape, so an agent that would pay can find this in
|
|
50
|
-
* the catalogue instead of finding it by being refused. The shape is defined
|
|
51
|
-
* for tools, not resources — a `resources/read` has no tool name or input
|
|
52
|
-
* schema to catalogue — so leave it undefined there rather than describing it
|
|
53
|
-
* as something it is not. Declared through `GateOptions.declareDiscovery`,
|
|
54
|
-
* and only for an entry that has actually been asked for.
|
|
55
|
-
*/
|
|
56
|
-
discovery?: Record<string, unknown>;
|
|
57
|
-
/** Passed through to the facilitator as call context, verbatim. */
|
|
58
|
-
context: unknown;
|
|
59
|
-
}
|
|
60
|
-
export interface GateOptions {
|
|
61
|
-
/**
|
|
62
|
-
* Built lazily, and allowed to throw. An unreachable facilitator throws out
|
|
63
|
-
* of `initialize()` rather than returning anything, and the gate turns that
|
|
64
|
-
* into a withheld paid entry instead of a 500 that would take the free tools
|
|
65
|
-
* in the same batch down with it.
|
|
66
|
-
*/
|
|
67
|
-
server: () => Promise<X402ServerPort>;
|
|
68
|
-
/** Which paid surface, if any, an envelope entry addresses. */
|
|
69
|
-
resolve: (entry: RpcRequest) => PaidSurface | null;
|
|
70
|
-
network: string;
|
|
71
|
-
payTo: string;
|
|
72
|
-
maxTimeoutSeconds: number;
|
|
73
|
-
serviceName: string;
|
|
74
|
-
tags: string[];
|
|
75
|
-
/** Must match the cap `handleMcp` will apply. See the passthrough below. */
|
|
76
|
-
maxBatch: number;
|
|
77
|
-
/** False when this deployment charges for nothing. Everything passes through. */
|
|
78
|
-
enabled?: boolean;
|
|
79
|
-
/**
|
|
80
|
-
* `@x402/extensions/bazaar`'s `declareDiscoveryExtension`, reached however
|
|
81
|
-
* the caller reaches it — this package does not import @x402 and will not
|
|
82
|
-
* start. Keep it a lazy `import()` on that side: it is only ever called for a
|
|
83
|
-
* surface somebody has actually requested, so the free path never loads it.
|
|
84
|
-
*/
|
|
85
|
-
declareDiscovery?: (discovery: Record<string, unknown>) => Promise<unknown>;
|
|
86
|
-
}
|
|
87
|
-
/**
|
|
88
|
-
* Verify payment for every paid entry, withhold the unpaid ones, and return a
|
|
89
|
-
* `finish` that reassembles the response.
|
|
90
|
-
*
|
|
91
|
-
* The ordering mirrors `withX402`: verify BEFORE dispatch, settle only AFTER
|
|
92
|
-
* the handler produced something that is not an error. A tool that raises
|
|
93
|
-
* cancels rather than settles — the caller pays for an answer, not an attempt.
|
|
94
|
-
*/
|
|
95
|
-
export declare function gatePaidCalls(raw: unknown, options: GateOptions): Promise<EnvelopeGate>;
|