@contextvm/sdk 0.1.48 → 0.2.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/dist/esm/core/constants.d.ts +3 -0
- package/dist/esm/core/constants.d.ts.map +1 -1
- package/dist/esm/core/constants.js +3 -0
- package/dist/esm/core/constants.js.map +1 -1
- package/dist/esm/core/utils/logger.d.ts +1 -1
- package/dist/esm/core/utils/logger.d.ts.map +1 -1
- package/dist/esm/core/utils/lru-cache.d.ts.map +1 -1
- package/dist/esm/core/utils/lru-cache.js +9 -1
- package/dist/esm/core/utils/lru-cache.js.map +1 -1
- package/dist/esm/core/utils/task-queue.d.ts +5 -0
- package/dist/esm/core/utils/task-queue.d.ts.map +1 -1
- package/dist/esm/core/utils/task-queue.js +11 -0
- package/dist/esm/core/utils/task-queue.js.map +1 -1
- package/dist/esm/core/utils/utils.d.ts +8 -0
- package/dist/esm/core/utils/utils.d.ts.map +1 -1
- package/dist/esm/core/utils/utils.js +23 -0
- package/dist/esm/core/utils/utils.js.map +1 -1
- package/dist/esm/relay/applesauce-relay-pool.d.ts +37 -4
- package/dist/esm/relay/applesauce-relay-pool.d.ts.map +1 -1
- package/dist/esm/relay/applesauce-relay-pool.js +165 -11
- package/dist/esm/relay/applesauce-relay-pool.js.map +1 -1
- package/dist/esm/transport/base-nostr-transport.d.ts +1 -1
- package/dist/esm/transport/base-nostr-transport.d.ts.map +1 -1
- package/dist/esm/transport/base-nostr-transport.js +8 -6
- package/dist/esm/transport/base-nostr-transport.js.map +1 -1
- package/dist/esm/transport/nostr-client/correlation-store.d.ts +60 -0
- package/dist/esm/transport/nostr-client/correlation-store.d.ts.map +1 -0
- package/dist/esm/transport/nostr-client/correlation-store.js +61 -0
- package/dist/esm/transport/nostr-client/correlation-store.js.map +1 -0
- package/dist/esm/transport/nostr-client/stateless-mode-handler.d.ts +24 -0
- package/dist/esm/transport/nostr-client/stateless-mode-handler.d.ts.map +1 -0
- package/dist/esm/transport/nostr-client/stateless-mode-handler.js +61 -0
- package/dist/esm/transport/nostr-client/stateless-mode-handler.js.map +1 -0
- package/dist/esm/transport/nostr-client-transport.d.ts +48 -24
- package/dist/esm/transport/nostr-client-transport.d.ts.map +1 -1
- package/dist/esm/transport/nostr-client-transport.js +92 -131
- package/dist/esm/transport/nostr-client-transport.js.map +1 -1
- package/dist/esm/transport/nostr-server/announcement-manager.d.ts +116 -0
- package/dist/esm/transport/nostr-server/announcement-manager.d.ts.map +1 -0
- package/dist/esm/transport/nostr-server/announcement-manager.js +288 -0
- package/dist/esm/transport/nostr-server/announcement-manager.js.map +1 -0
- package/dist/esm/transport/nostr-server/authorization-policy.d.ts +74 -0
- package/dist/esm/transport/nostr-server/authorization-policy.d.ts.map +1 -0
- package/dist/esm/transport/nostr-server/authorization-policy.js +91 -0
- package/dist/esm/transport/nostr-server/authorization-policy.js.map +1 -0
- package/dist/esm/transport/nostr-server/correlation-store.d.ts +102 -0
- package/dist/esm/transport/nostr-server/correlation-store.d.ts.map +1 -0
- package/dist/esm/transport/nostr-server/correlation-store.js +167 -0
- package/dist/esm/transport/nostr-server/correlation-store.js.map +1 -0
- package/dist/esm/transport/nostr-server/session-store.d.ts +99 -0
- package/dist/esm/transport/nostr-server/session-store.d.ts.map +1 -0
- package/dist/esm/transport/nostr-server/session-store.js +123 -0
- package/dist/esm/transport/nostr-server/session-store.js.map +1 -0
- package/dist/esm/transport/nostr-server-transport.d.ts +18 -63
- package/dist/esm/transport/nostr-server-transport.d.ts.map +1 -1
- package/dist/esm/transport/nostr-server-transport.js +135 -378
- package/dist/esm/transport/nostr-server-transport.js.map +1 -1
- package/package.json +11 -12
|
@@ -0,0 +1,288 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Internal announcement manager for NostrServerTransport.
|
|
3
|
+
* Handles public server announcements including initialization handshake,
|
|
4
|
+
* schema mapping, and deletion events.
|
|
5
|
+
*
|
|
6
|
+
*/
|
|
7
|
+
import { InitializeResultSchema, ListPromptsResultSchema, ListResourcesResultSchema, ListResourceTemplatesResultSchema, ListToolsResultSchema, isJSONRPCResultResponse, } from '@modelcontextprotocol/sdk/types.js';
|
|
8
|
+
import { EventDeletion } from 'nostr-tools/kinds';
|
|
9
|
+
import { LATEST_PROTOCOL_VERSION } from '@modelcontextprotocol/sdk/types.js';
|
|
10
|
+
import { announcementMethods, SERVER_ANNOUNCEMENT_KIND, TOOLS_LIST_KIND, RESOURCES_LIST_KIND, RESOURCETEMPLATES_LIST_KIND, PROMPTS_LIST_KIND, NOSTR_TAGS, INITIALIZE_METHOD, NOTIFICATIONS_INITIALIZED_METHOD, } from '../../core/index.js';
|
|
11
|
+
import { EncryptionMode } from '../../core/interfaces.js';
|
|
12
|
+
/**
|
|
13
|
+
* Internal manager for public server announcements.
|
|
14
|
+
*
|
|
15
|
+
* This class encapsulates the announcement flow:
|
|
16
|
+
* - Initialize handshake with timeout
|
|
17
|
+
* - Schema-to-kind mapping for different announcement types
|
|
18
|
+
* - Publishing announcements as Nostr events
|
|
19
|
+
* - Deleting announcements via deletion events
|
|
20
|
+
*/
|
|
21
|
+
export class AnnouncementManager {
|
|
22
|
+
constructor(options) {
|
|
23
|
+
this.isInitialized = false;
|
|
24
|
+
this.serverInfo = options.serverInfo;
|
|
25
|
+
this.encryptionMode = options.encryptionMode;
|
|
26
|
+
this.onSendMessage = options.onSendMessage;
|
|
27
|
+
this.onPublishEvent = options.onPublishEvent;
|
|
28
|
+
this.onSignEvent = options.onSignEvent;
|
|
29
|
+
this.onGetPublicKey = options.onGetPublicKey;
|
|
30
|
+
this.onSubscribe = options.onSubscribe;
|
|
31
|
+
this.logger = options.logger;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Generates common tags from server information for use in Nostr events.
|
|
35
|
+
* @returns Array of tag arrays for Nostr events.
|
|
36
|
+
*/
|
|
37
|
+
getCommonTags() {
|
|
38
|
+
var _a, _b, _c, _d;
|
|
39
|
+
if (this.cachedCommonTags) {
|
|
40
|
+
return this.cachedCommonTags;
|
|
41
|
+
}
|
|
42
|
+
const commonTags = [];
|
|
43
|
+
if ((_a = this.serverInfo) === null || _a === void 0 ? void 0 : _a.name) {
|
|
44
|
+
commonTags.push([NOSTR_TAGS.NAME, this.serverInfo.name]);
|
|
45
|
+
}
|
|
46
|
+
if ((_b = this.serverInfo) === null || _b === void 0 ? void 0 : _b.about) {
|
|
47
|
+
commonTags.push([NOSTR_TAGS.ABOUT, this.serverInfo.about]);
|
|
48
|
+
}
|
|
49
|
+
if ((_c = this.serverInfo) === null || _c === void 0 ? void 0 : _c.website) {
|
|
50
|
+
commonTags.push([NOSTR_TAGS.WEBSITE, this.serverInfo.website]);
|
|
51
|
+
}
|
|
52
|
+
if ((_d = this.serverInfo) === null || _d === void 0 ? void 0 : _d.picture) {
|
|
53
|
+
commonTags.push([NOSTR_TAGS.PICTURE, this.serverInfo.picture]);
|
|
54
|
+
}
|
|
55
|
+
if (this.encryptionMode !== EncryptionMode.DISABLED) {
|
|
56
|
+
commonTags.push([NOSTR_TAGS.SUPPORT_ENCRYPTION]);
|
|
57
|
+
}
|
|
58
|
+
this.cachedCommonTags = commonTags;
|
|
59
|
+
return commonTags;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Gets the announcement mapping for schema-to-kind conversion.
|
|
63
|
+
* @returns Array of announcement mappings.
|
|
64
|
+
*/
|
|
65
|
+
getAnnouncementMapping() {
|
|
66
|
+
const commonTags = this.getCommonTags();
|
|
67
|
+
return [
|
|
68
|
+
{
|
|
69
|
+
schema: InitializeResultSchema,
|
|
70
|
+
kind: SERVER_ANNOUNCEMENT_KIND,
|
|
71
|
+
tags: commonTags,
|
|
72
|
+
},
|
|
73
|
+
{ schema: ListToolsResultSchema, kind: TOOLS_LIST_KIND, tags: [] },
|
|
74
|
+
{
|
|
75
|
+
schema: ListResourcesResultSchema,
|
|
76
|
+
kind: RESOURCES_LIST_KIND,
|
|
77
|
+
tags: [],
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
schema: ListResourceTemplatesResultSchema,
|
|
81
|
+
kind: RESOURCETEMPLATES_LIST_KIND,
|
|
82
|
+
tags: [],
|
|
83
|
+
},
|
|
84
|
+
{ schema: ListPromptsResultSchema, kind: PROMPTS_LIST_KIND, tags: [] },
|
|
85
|
+
];
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Initiates the process of fetching announcement data from the server's internal logic.
|
|
89
|
+
* This method properly handles the initialization handshake by first sending
|
|
90
|
+
* the initialize request, waiting for the response, and then proceeding with other announcements.
|
|
91
|
+
*/
|
|
92
|
+
async getAnnouncementData() {
|
|
93
|
+
try {
|
|
94
|
+
const initializeParams = {
|
|
95
|
+
protocolVersion: LATEST_PROTOCOL_VERSION,
|
|
96
|
+
capabilities: {},
|
|
97
|
+
clientInfo: {
|
|
98
|
+
name: 'DummyClient',
|
|
99
|
+
version: '1.0.0',
|
|
100
|
+
},
|
|
101
|
+
};
|
|
102
|
+
// Send the initialize request if not already initialized
|
|
103
|
+
if (!this.isInitialized) {
|
|
104
|
+
const initializeMessage = {
|
|
105
|
+
jsonrpc: '2.0',
|
|
106
|
+
id: 'announcement',
|
|
107
|
+
method: INITIALIZE_METHOD,
|
|
108
|
+
params: initializeParams,
|
|
109
|
+
};
|
|
110
|
+
this.logger.info('Sending initialize request for announcement');
|
|
111
|
+
this.onSendMessage(initializeMessage);
|
|
112
|
+
}
|
|
113
|
+
try {
|
|
114
|
+
// Wait for initialization to complete
|
|
115
|
+
await this.waitForInitialization();
|
|
116
|
+
// Send all announcements now that we're initialized
|
|
117
|
+
for (const [key, methodValue] of Object.entries(announcementMethods)) {
|
|
118
|
+
this.logger.info('Sending announcement', { key, methodValue });
|
|
119
|
+
const message = {
|
|
120
|
+
jsonrpc: '2.0',
|
|
121
|
+
id: 'announcement',
|
|
122
|
+
method: methodValue,
|
|
123
|
+
params: key === 'server' ? initializeParams : {},
|
|
124
|
+
};
|
|
125
|
+
this.onSendMessage(message);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
catch (error) {
|
|
129
|
+
this.logger.warn('Server not initialized after waiting, skipping announcements', { error: error instanceof Error ? error.message : error });
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
catch (error) {
|
|
133
|
+
this.logger.error('Error in getAnnouncementData', {
|
|
134
|
+
error: error instanceof Error ? error.message : String(error),
|
|
135
|
+
stack: error instanceof Error ? error.stack : undefined,
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Waits for the server to be initialized with a timeout.
|
|
141
|
+
* @returns Promise that resolves when initialized or after 10-second timeout.
|
|
142
|
+
* The method will always resolve, allowing announcements to proceed.
|
|
143
|
+
*/
|
|
144
|
+
async waitForInitialization() {
|
|
145
|
+
if (this.isInitialized)
|
|
146
|
+
return;
|
|
147
|
+
if (!this.initializationPromise) {
|
|
148
|
+
this.initializationPromise = new Promise((resolve) => {
|
|
149
|
+
this.initializationResolver = resolve;
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
const timeout = new Promise((_, reject) => setTimeout(() => reject(new Error('Initialization timeout')), 10000));
|
|
153
|
+
try {
|
|
154
|
+
await Promise.race([this.initializationPromise, timeout]);
|
|
155
|
+
}
|
|
156
|
+
catch (_a) {
|
|
157
|
+
this.logger.warn('Server initialization not completed within timeout, proceeding with announcements');
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Handles the JSON-RPC responses for public server announcements and publishes
|
|
162
|
+
* them as Nostr events to the configured relays.
|
|
163
|
+
* @param message The JSON-RPC response containing the announcement data.
|
|
164
|
+
* @returns true if the message was an announcement response and was handled, false otherwise.
|
|
165
|
+
*/
|
|
166
|
+
async handleAnnouncementResponse(message) {
|
|
167
|
+
var _a;
|
|
168
|
+
// Only process announcement responses
|
|
169
|
+
if (message.id !== 'announcement') {
|
|
170
|
+
return false;
|
|
171
|
+
}
|
|
172
|
+
if (!isJSONRPCResultResponse(message) || !message.result) {
|
|
173
|
+
return true; // Was an announcement response, but no result
|
|
174
|
+
}
|
|
175
|
+
// Handle initialize response
|
|
176
|
+
if (InitializeResultSchema.safeParse(message.result).success) {
|
|
177
|
+
this.isInitialized = true;
|
|
178
|
+
(_a = this.initializationResolver) === null || _a === void 0 ? void 0 : _a.call(this); // Resolve waiting promise
|
|
179
|
+
// Clean up promise references to prevent memory leaks
|
|
180
|
+
this.initializationPromise = undefined;
|
|
181
|
+
this.initializationResolver = undefined;
|
|
182
|
+
// Send the initialized notification
|
|
183
|
+
const initializedNotification = {
|
|
184
|
+
jsonrpc: '2.0',
|
|
185
|
+
method: NOTIFICATIONS_INITIALIZED_METHOD,
|
|
186
|
+
};
|
|
187
|
+
this.onSendMessage(initializedNotification);
|
|
188
|
+
this.logger.info('Initialized');
|
|
189
|
+
}
|
|
190
|
+
// Publish the announcement as a Nostr event
|
|
191
|
+
await this.publishAnnouncement(message.result);
|
|
192
|
+
return true;
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* Publishes an announcement as a Nostr event.
|
|
196
|
+
* @param result The announcement result to publish.
|
|
197
|
+
*/
|
|
198
|
+
async publishAnnouncement(result) {
|
|
199
|
+
try {
|
|
200
|
+
const recipientPubkey = await this.onGetPublicKey();
|
|
201
|
+
const announcementMapping = this.getAnnouncementMapping();
|
|
202
|
+
for (const mapping of announcementMapping) {
|
|
203
|
+
if (mapping.schema.safeParse(result).success) {
|
|
204
|
+
const eventTemplate = {
|
|
205
|
+
kind: mapping.kind,
|
|
206
|
+
content: JSON.stringify(result),
|
|
207
|
+
tags: mapping.tags,
|
|
208
|
+
created_at: Math.floor(Date.now() / 1000),
|
|
209
|
+
pubkey: recipientPubkey,
|
|
210
|
+
};
|
|
211
|
+
const signedEvent = await this.onSignEvent(eventTemplate);
|
|
212
|
+
await this.onPublishEvent(signedEvent);
|
|
213
|
+
this.logger.debug('Published announcement event', {
|
|
214
|
+
kind: mapping.kind,
|
|
215
|
+
eventId: signedEvent.id,
|
|
216
|
+
});
|
|
217
|
+
break;
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
catch (error) {
|
|
222
|
+
this.logger.error('Error publishing announcement', {
|
|
223
|
+
error: error instanceof Error ? error.message : String(error),
|
|
224
|
+
stack: error instanceof Error ? error.stack : undefined,
|
|
225
|
+
});
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* Deletes server announcements and capability listings by publishing deletion events.
|
|
230
|
+
* This method queries for existing announcement events and publishes deletion events (kind 5)
|
|
231
|
+
* to remove them from the relay network.
|
|
232
|
+
* @param reason Optional reason for deletion (default: 'Service offline').
|
|
233
|
+
* @returns Promise that resolves to an array of deletion events that were published.
|
|
234
|
+
*/
|
|
235
|
+
async deleteAnnouncement(reason = 'Service offline') {
|
|
236
|
+
const publicKey = await this.onGetPublicKey();
|
|
237
|
+
const allDeletedEvents = [];
|
|
238
|
+
const kinds = [
|
|
239
|
+
SERVER_ANNOUNCEMENT_KIND,
|
|
240
|
+
TOOLS_LIST_KIND,
|
|
241
|
+
RESOURCES_LIST_KIND,
|
|
242
|
+
RESOURCETEMPLATES_LIST_KIND,
|
|
243
|
+
PROMPTS_LIST_KIND,
|
|
244
|
+
];
|
|
245
|
+
for (const kind of kinds) {
|
|
246
|
+
const eventsForKind = [];
|
|
247
|
+
const filter = {
|
|
248
|
+
kinds: [kind],
|
|
249
|
+
authors: [publicKey],
|
|
250
|
+
};
|
|
251
|
+
// Collect events for this specific kind
|
|
252
|
+
await this.onSubscribe([filter], (event) => {
|
|
253
|
+
try {
|
|
254
|
+
eventsForKind.push(event);
|
|
255
|
+
}
|
|
256
|
+
catch (error) {
|
|
257
|
+
this.logger.error('Error in relay subscription event collection', {
|
|
258
|
+
error: error instanceof Error ? error.message : String(error),
|
|
259
|
+
eventId: event.id,
|
|
260
|
+
});
|
|
261
|
+
}
|
|
262
|
+
});
|
|
263
|
+
if (!eventsForKind.length) {
|
|
264
|
+
this.logger.info(`No events found for kind ${kind} to delete`);
|
|
265
|
+
continue;
|
|
266
|
+
}
|
|
267
|
+
const deletionEventTemplate = {
|
|
268
|
+
kind: EventDeletion,
|
|
269
|
+
pubkey: publicKey,
|
|
270
|
+
content: reason,
|
|
271
|
+
tags: eventsForKind.map((ev) => ['e', ev.id]),
|
|
272
|
+
created_at: Math.floor(Date.now() / 1000),
|
|
273
|
+
};
|
|
274
|
+
const deletionEvent = await this.onSignEvent(deletionEventTemplate);
|
|
275
|
+
await this.onPublishEvent(deletionEvent);
|
|
276
|
+
this.logger.info(`Published deletion event for kind ${kind} (${eventsForKind.length} events)`);
|
|
277
|
+
allDeletedEvents.push(...eventsForKind);
|
|
278
|
+
}
|
|
279
|
+
return allDeletedEvents;
|
|
280
|
+
}
|
|
281
|
+
/**
|
|
282
|
+
* Checks if the manager is initialized.
|
|
283
|
+
*/
|
|
284
|
+
get initialized() {
|
|
285
|
+
return this.isInitialized;
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
//# sourceMappingURL=announcement-manager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"announcement-manager.js","sourceRoot":"","sources":["../../../../src/transport/nostr-server/announcement-manager.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAEL,sBAAsB,EACtB,uBAAuB,EACvB,yBAAyB,EACzB,iCAAiC,EACjC,qBAAqB,EAGrB,uBAAuB,GACxB,MAAM,oCAAoC,CAAC;AAG5C,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAClD,OAAO,EAAE,uBAAuB,EAAE,MAAM,oCAAoC,CAAC;AAC7E,OAAO,EACL,mBAAmB,EACnB,wBAAwB,EACxB,eAAe,EACf,mBAAmB,EACnB,2BAA2B,EAC3B,iBAAiB,EACjB,UAAU,EACV,iBAAiB,EACjB,gCAAgC,GACjC,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAqD1D;;;;;;;;GAQG;AACH,MAAM,OAAO,mBAAmB;IAoB9B,YAAY,OAAmC;QALvC,kBAAa,GAAG,KAAK,CAAC;QAM5B,IAAI,CAAC,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC;QACrC,IAAI,CAAC,cAAc,GAAG,OAAO,CAAC,cAAc,CAAC;QAC7C,IAAI,CAAC,aAAa,GAAG,OAAO,CAAC,aAAa,CAAC;QAC3C,IAAI,CAAC,cAAc,GAAG,OAAO,CAAC,cAAc,CAAC;QAC7C,IAAI,CAAC,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC;QACvC,IAAI,CAAC,cAAc,GAAG,OAAO,CAAC,cAAc,CAAC;QAC7C,IAAI,CAAC,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC;QACvC,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAC/B,CAAC;IAED;;;OAGG;IACH,aAAa;;QACX,IAAI,IAAI,CAAC,gBAAgB,EAAE,CAAC;YAC1B,OAAO,IAAI,CAAC,gBAAgB,CAAC;QAC/B,CAAC;QAED,MAAM,UAAU,GAAe,EAAE,CAAC;QAClC,IAAI,MAAA,IAAI,CAAC,UAAU,0CAAE,IAAI,EAAE,CAAC;YAC1B,UAAU,CAAC,IAAI,CAAC,CAAC,UAAU,CAAC,IAAI,EAAE,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC;QAC3D,CAAC;QACD,IAAI,MAAA,IAAI,CAAC,UAAU,0CAAE,KAAK,EAAE,CAAC;YAC3B,UAAU,CAAC,IAAI,CAAC,CAAC,UAAU,CAAC,KAAK,EAAE,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC;QAC7D,CAAC;QACD,IAAI,MAAA,IAAI,CAAC,UAAU,0CAAE,OAAO,EAAE,CAAC;YAC7B,UAAU,CAAC,IAAI,CAAC,CAAC,UAAU,CAAC,OAAO,EAAE,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC;QACjE,CAAC;QACD,IAAI,MAAA,IAAI,CAAC,UAAU,0CAAE,OAAO,EAAE,CAAC;YAC7B,UAAU,CAAC,IAAI,CAAC,CAAC,UAAU,CAAC,OAAO,EAAE,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC;QACjE,CAAC;QACD,IAAI,IAAI,CAAC,cAAc,KAAK,cAAc,CAAC,QAAQ,EAAE,CAAC;YACpD,UAAU,CAAC,IAAI,CAAC,CAAC,UAAU,CAAC,kBAAkB,CAAC,CAAC,CAAC;QACnD,CAAC;QAED,IAAI,CAAC,gBAAgB,GAAG,UAAU,CAAC;QACnC,OAAO,UAAU,CAAC;IACpB,CAAC;IAED;;;OAGG;IACK,sBAAsB;QAC5B,MAAM,UAAU,GAAG,IAAI,CAAC,aAAa,EAAE,CAAC;QAExC,OAAO;YACL;gBACE,MAAM,EAAE,sBAAsB;gBAC9B,IAAI,EAAE,wBAAwB;gBAC9B,IAAI,EAAE,UAAU;aACjB;YACD,EAAE,MAAM,EAAE,qBAAqB,EAAE,IAAI,EAAE,eAAe,EAAE,IAAI,EAAE,EAAE,EAAE;YAClE;gBACE,MAAM,EAAE,yBAAyB;gBACjC,IAAI,EAAE,mBAAmB;gBACzB,IAAI,EAAE,EAAE;aACT;YACD;gBACE,MAAM,EAAE,iCAAiC;gBACzC,IAAI,EAAE,2BAA2B;gBACjC,IAAI,EAAE,EAAE;aACT;YACD,EAAE,MAAM,EAAE,uBAAuB,EAAE,IAAI,EAAE,iBAAiB,EAAE,IAAI,EAAE,EAAE,EAAE;SACvE,CAAC;IACJ,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,mBAAmB;QACvB,IAAI,CAAC;YACH,MAAM,gBAAgB,GAAgC;gBACpD,eAAe,EAAE,uBAAuB;gBACxC,YAAY,EAAE,EAAE;gBAChB,UAAU,EAAE;oBACV,IAAI,EAAE,aAAa;oBACnB,OAAO,EAAE,OAAO;iBACjB;aACF,CAAC;YAEF,yDAAyD;YACzD,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,CAAC;gBACxB,MAAM,iBAAiB,GAAmB;oBACxC,OAAO,EAAE,KAAK;oBACd,EAAE,EAAE,cAAc;oBAClB,MAAM,EAAE,iBAAiB;oBACzB,MAAM,EAAE,gBAAgB;iBACzB,CAAC;gBAEF,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,6CAA6C,CAAC,CAAC;gBAChE,IAAI,CAAC,aAAa,CAAC,iBAAiB,CAAC,CAAC;YACxC,CAAC;YAED,IAAI,CAAC;gBACH,sCAAsC;gBACtC,MAAM,IAAI,CAAC,qBAAqB,EAAE,CAAC;gBAEnC,oDAAoD;gBACpD,KAAK,MAAM,CAAC,GAAG,EAAE,WAAW,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,mBAAmB,CAAC,EAAE,CAAC;oBACrE,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,sBAAsB,EAAE,EAAE,GAAG,EAAE,WAAW,EAAE,CAAC,CAAC;oBAC/D,MAAM,OAAO,GAAmB;wBAC9B,OAAO,EAAE,KAAK;wBACd,EAAE,EAAE,cAAc;wBAClB,MAAM,EAAE,WAAW;wBACnB,MAAM,EAAE,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,EAAE;qBACjD,CAAC;oBACF,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;gBAC9B,CAAC;YACH,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,IAAI,CAAC,MAAM,CAAC,IAAI,CACd,8DAA8D,EAC9D,EAAE,KAAK,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,EAAE,CAC1D,CAAC;YACJ,CAAC;QACH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,8BAA8B,EAAE;gBAChD,KAAK,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;gBAC7D,KAAK,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS;aACxD,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED;;;;OAIG;IACK,KAAK,CAAC,qBAAqB;QACjC,IAAI,IAAI,CAAC,aAAa;YAAE,OAAO;QAE/B,IAAI,CAAC,IAAI,CAAC,qBAAqB,EAAE,CAAC;YAChC,IAAI,CAAC,qBAAqB,GAAG,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;gBACnD,IAAI,CAAC,sBAAsB,GAAG,OAAO,CAAC;YACxC,CAAC,CAAC,CAAC;QACL,CAAC;QAED,MAAM,OAAO,GAAG,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE,CACxC,UAAU,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,wBAAwB,CAAC,CAAC,EAAE,KAAK,CAAC,CACrE,CAAC;QAEF,IAAI,CAAC;YACH,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,qBAAqB,EAAE,OAAO,CAAC,CAAC,CAAC;QAC5D,CAAC;QAAC,WAAM,CAAC;YACP,IAAI,CAAC,MAAM,CAAC,IAAI,CACd,mFAAmF,CACpF,CAAC;QACJ,CAAC;IACH,CAAC;IAED;;;;;OAKG;IACH,KAAK,CAAC,0BAA0B,CAAC,OAAwB;;QACvD,sCAAsC;QACtC,IAAI,OAAO,CAAC,EAAE,KAAK,cAAc,EAAE,CAAC;YAClC,OAAO,KAAK,CAAC;QACf,CAAC;QAED,IAAI,CAAC,uBAAuB,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC;YACzD,OAAO,IAAI,CAAC,CAAC,8CAA8C;QAC7D,CAAC;QAED,6BAA6B;QAC7B,IAAI,sBAAsB,CAAC,SAAS,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,OAAO,EAAE,CAAC;YAC7D,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC;YAC1B,MAAA,IAAI,CAAC,sBAAsB,oDAAI,CAAC,CAAC,0BAA0B;YAE3D,sDAAsD;YACtD,IAAI,CAAC,qBAAqB,GAAG,SAAS,CAAC;YACvC,IAAI,CAAC,sBAAsB,GAAG,SAAS,CAAC;YAExC,oCAAoC;YACpC,MAAM,uBAAuB,GAAmB;gBAC9C,OAAO,EAAE,KAAK;gBACd,MAAM,EAAE,gCAAgC;aACzC,CAAC;YACF,IAAI,CAAC,aAAa,CAAC,uBAAuB,CAAC,CAAC;YAC5C,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;QAClC,CAAC;QAED,4CAA4C;QAC5C,MAAM,IAAI,CAAC,mBAAmB,CAAC,OAAO,CAAC,MAAwB,CAAC,CAAC;QAEjE,OAAO,IAAI,CAAC;IACd,CAAC;IAED;;;OAGG;IACK,KAAK,CAAC,mBAAmB,CAAC,MAAsB;QACtD,IAAI,CAAC;YACH,MAAM,eAAe,GAAG,MAAM,IAAI,CAAC,cAAc,EAAE,CAAC;YACpD,MAAM,mBAAmB,GAAG,IAAI,CAAC,sBAAsB,EAAE,CAAC;YAE1D,KAAK,MAAM,OAAO,IAAI,mBAAmB,EAAE,CAAC;gBAC1C,IAAI,OAAO,CAAC,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,OAAO,EAAE,CAAC;oBAC7C,MAAM,aAAa,GAAG;wBACpB,IAAI,EAAE,OAAO,CAAC,IAAI;wBAClB,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC;wBAC/B,IAAI,EAAE,OAAO,CAAC,IAAI;wBAClB,UAAU,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC;wBACzC,MAAM,EAAE,eAAe;qBACxB,CAAC;oBAEF,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC,WAAW,CACxC,aAA2B,CAC5B,CAAC;oBACF,MAAM,IAAI,CAAC,cAAc,CAAC,WAAW,CAAC,CAAC;oBACvC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,8BAA8B,EAAE;wBAChD,IAAI,EAAE,OAAO,CAAC,IAAI;wBAClB,OAAO,EAAE,WAAW,CAAC,EAAE;qBACxB,CAAC,CAAC;oBACH,MAAM;gBACR,CAAC;YACH,CAAC;QACH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,+BAA+B,EAAE;gBACjD,KAAK,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;gBAC7D,KAAK,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS;aACxD,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED;;;;;;OAMG;IACH,KAAK,CAAC,kBAAkB,CACtB,SAAiB,iBAAiB;QAElC,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,cAAc,EAAE,CAAC;QAC9C,MAAM,gBAAgB,GAAiB,EAAE,CAAC;QAE1C,MAAM,KAAK,GAAG;YACZ,wBAAwB;YACxB,eAAe;YACf,mBAAmB;YACnB,2BAA2B;YAC3B,iBAAiB;SAClB,CAAC;QAEF,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,MAAM,aAAa,GAAiB,EAAE,CAAC;YACvC,MAAM,MAAM,GAAG;gBACb,KAAK,EAAE,CAAC,IAAI,CAAC;gBACb,OAAO,EAAE,CAAC,SAAS,CAAC;aACrB,CAAC;YAEF,wCAAwC;YACxC,MAAM,IAAI,CAAC,WAAW,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,KAAiB,EAAE,EAAE;gBACrD,IAAI,CAAC;oBACH,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;gBAC5B,CAAC;gBAAC,OAAO,KAAK,EAAE,CAAC;oBACf,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,8CAA8C,EAAE;wBAChE,KAAK,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;wBAC7D,OAAO,EAAE,KAAK,CAAC,EAAE;qBAClB,CAAC,CAAC;gBACL,CAAC;YACH,CAAC,CAAC,CAAC;YAEH,IAAI,CAAC,aAAa,CAAC,MAAM,EAAE,CAAC;gBAC1B,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,4BAA4B,IAAI,YAAY,CAAC,CAAC;gBAC/D,SAAS;YACX,CAAC;YAED,MAAM,qBAAqB,GAAG;gBAC5B,IAAI,EAAE,aAAa;gBACnB,MAAM,EAAE,SAAS;gBACjB,OAAO,EAAE,MAAM;gBACf,IAAI,EAAE,aAAa,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC;gBAC7C,UAAU,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC;aAC1C,CAAC;YAEF,MAAM,aAAa,GAAG,MAAM,IAAI,CAAC,WAAW,CAC1C,qBAAmC,CACpC,CAAC;YAEF,MAAM,IAAI,CAAC,cAAc,CAAC,aAAa,CAAC,CAAC;YACzC,IAAI,CAAC,MAAM,CAAC,IAAI,CACd,qCAAqC,IAAI,KAAK,aAAa,CAAC,MAAM,UAAU,CAC7E,CAAC;YAEF,gBAAgB,CAAC,IAAI,CAAC,GAAG,aAAa,CAAC,CAAC;QAC1C,CAAC;QACD,OAAO,gBAAgB,CAAC;IAC1B,CAAC;IAED;;OAEG;IACH,IAAI,WAAW;QACb,OAAO,IAAI,CAAC,aAAa,CAAC;IAC5B,CAAC;CACF"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Internal authorization policy for NostrServerTransport.
|
|
3
|
+
* Handles whitelist and excluded-capability checks.
|
|
4
|
+
*
|
|
5
|
+
* This module is not exported from the public API.
|
|
6
|
+
*/
|
|
7
|
+
import type { JSONRPCMessage } from '@modelcontextprotocol/sdk/types.js';
|
|
8
|
+
/**
|
|
9
|
+
* Represents a capability exclusion pattern that can bypass whitelisting.
|
|
10
|
+
* Can be either a method-only pattern (e.g., 'tools/list') or a method + name pattern (e.g., 'tools/call, get_weather').
|
|
11
|
+
*/
|
|
12
|
+
export interface CapabilityExclusion {
|
|
13
|
+
/** The JSON-RPC method to exclude from whitelisting (e.g., 'tools/call', 'tools/list') */
|
|
14
|
+
method: string;
|
|
15
|
+
/** Optional capability name to specifically exclude (e.g., 'get_weather') */
|
|
16
|
+
name?: string;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Authorization decision result.
|
|
20
|
+
*/
|
|
21
|
+
export type AuthorizationDecision = {
|
|
22
|
+
allowed: true;
|
|
23
|
+
} | {
|
|
24
|
+
allowed: false;
|
|
25
|
+
shouldReplyUnauthorized: boolean;
|
|
26
|
+
};
|
|
27
|
+
/**
|
|
28
|
+
* Options for configuring the AuthorizationPolicy.
|
|
29
|
+
*/
|
|
30
|
+
export interface AuthorizationPolicyOptions {
|
|
31
|
+
/** Set of allowed public keys (whitelist). If undefined, all clients are allowed. */
|
|
32
|
+
allowedPublicKeys?: Set<string>;
|
|
33
|
+
/** List of capabilities that are excluded from public key whitelisting requirements */
|
|
34
|
+
excludedCapabilities?: CapabilityExclusion[];
|
|
35
|
+
/** Whether this is a public server (affects unauthorized response behavior) */
|
|
36
|
+
isPublicServer?: boolean;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Internal policy for authorizing incoming messages.
|
|
40
|
+
*
|
|
41
|
+
* This class encapsulates the authorization logic, making it easier to test
|
|
42
|
+
* and maintain. It handles:
|
|
43
|
+
* - Whitelist checking
|
|
44
|
+
* - Excluded capability checking
|
|
45
|
+
* - Determining whether to send an unauthorized response
|
|
46
|
+
*/
|
|
47
|
+
export declare class AuthorizationPolicy {
|
|
48
|
+
private readonly allowedPublicKeys?;
|
|
49
|
+
private readonly excludedCapabilities?;
|
|
50
|
+
readonly isPublicServer?: boolean;
|
|
51
|
+
constructor(options?: AuthorizationPolicyOptions);
|
|
52
|
+
/**
|
|
53
|
+
* Checks if a capability is excluded from whitelisting requirements.
|
|
54
|
+
* @param method The JSON-RPC method (e.g., 'tools/call', 'tools/list')
|
|
55
|
+
* @param name Optional capability name for method-specific exclusions (e.g., 'get_weather')
|
|
56
|
+
* @returns true if the capability should bypass whitelisting, false otherwise
|
|
57
|
+
*/
|
|
58
|
+
private isCapabilityExcluded;
|
|
59
|
+
/**
|
|
60
|
+
* Determines whether a message should be allowed based on authorization policy.
|
|
61
|
+
*
|
|
62
|
+
* @param clientPubkey The client's public key
|
|
63
|
+
* @param message The incoming JSON-RPC message
|
|
64
|
+
* @returns Authorization decision indicating whether the message is allowed
|
|
65
|
+
*/
|
|
66
|
+
authorize(clientPubkey: string, message: JSONRPCMessage): AuthorizationDecision;
|
|
67
|
+
/**
|
|
68
|
+
* Checks if a client public key is in the allowed whitelist.
|
|
69
|
+
* @param clientPubkey The client's public key
|
|
70
|
+
* @returns true if the client is whitelisted, false otherwise
|
|
71
|
+
*/
|
|
72
|
+
isClientWhitelisted(clientPubkey: string): boolean;
|
|
73
|
+
}
|
|
74
|
+
//# sourceMappingURL=authorization-policy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"authorization-policy.d.ts","sourceRoot":"","sources":["../../../../src/transport/nostr-server/authorization-policy.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AAMzE;;;GAGG;AACH,MAAM,WAAW,mBAAmB;IAClC,0FAA0F;IAC1F,MAAM,EAAE,MAAM,CAAC;IACf,6EAA6E;IAC7E,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED;;GAEG;AACH,MAAM,MAAM,qBAAqB,GAC7B;IAAE,OAAO,EAAE,IAAI,CAAA;CAAE,GACjB;IAAE,OAAO,EAAE,KAAK,CAAC;IAAC,uBAAuB,EAAE,OAAO,CAAA;CAAE,CAAC;AAEzD;;GAEG;AACH,MAAM,WAAW,0BAA0B;IACzC,qFAAqF;IACrF,iBAAiB,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAChC,uFAAuF;IACvF,oBAAoB,CAAC,EAAE,mBAAmB,EAAE,CAAC;IAC7C,+EAA+E;IAC/E,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED;;;;;;;;GAQG;AACH,qBAAa,mBAAmB;IAC9B,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAC,CAAc;IACjD,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CAAC,CAAwB;IAC9D,SAAgB,cAAc,CAAC,EAAE,OAAO,CAAC;gBAE7B,OAAO,GAAE,0BAA+B;IAMpD;;;;;OAKG;IACH,OAAO,CAAC,oBAAoB;IA6B5B;;;;;;OAMG;IACH,SAAS,CACP,YAAY,EAAE,MAAM,EACpB,OAAO,EAAE,cAAc,GACtB,qBAAqB;IA2BxB;;;;OAIG;IACH,mBAAmB,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO;CAMnD"}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Internal authorization policy for NostrServerTransport.
|
|
3
|
+
* Handles whitelist and excluded-capability checks.
|
|
4
|
+
*
|
|
5
|
+
* This module is not exported from the public API.
|
|
6
|
+
*/
|
|
7
|
+
import { INITIALIZE_METHOD, NOTIFICATIONS_INITIALIZED_METHOD, } from '@contextvm/sdk/core/constants.js';
|
|
8
|
+
import { isJSONRPCRequest, isJSONRPCNotification, } from '@modelcontextprotocol/sdk/types.js';
|
|
9
|
+
/**
|
|
10
|
+
* Internal policy for authorizing incoming messages.
|
|
11
|
+
*
|
|
12
|
+
* This class encapsulates the authorization logic, making it easier to test
|
|
13
|
+
* and maintain. It handles:
|
|
14
|
+
* - Whitelist checking
|
|
15
|
+
* - Excluded capability checking
|
|
16
|
+
* - Determining whether to send an unauthorized response
|
|
17
|
+
*/
|
|
18
|
+
export class AuthorizationPolicy {
|
|
19
|
+
constructor(options = {}) {
|
|
20
|
+
this.allowedPublicKeys = options.allowedPublicKeys;
|
|
21
|
+
this.excludedCapabilities = options.excludedCapabilities;
|
|
22
|
+
this.isPublicServer = options.isPublicServer;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Checks if a capability is excluded from whitelisting requirements.
|
|
26
|
+
* @param method The JSON-RPC method (e.g., 'tools/call', 'tools/list')
|
|
27
|
+
* @param name Optional capability name for method-specific exclusions (e.g., 'get_weather')
|
|
28
|
+
* @returns true if the capability should bypass whitelisting, false otherwise
|
|
29
|
+
*/
|
|
30
|
+
isCapabilityExcluded(method, name) {
|
|
31
|
+
var _a;
|
|
32
|
+
// Always allow fundamental MCP methods for connection establishment
|
|
33
|
+
if (method === INITIALIZE_METHOD ||
|
|
34
|
+
method === NOTIFICATIONS_INITIALIZED_METHOD) {
|
|
35
|
+
return true;
|
|
36
|
+
}
|
|
37
|
+
if (!((_a = this.excludedCapabilities) === null || _a === void 0 ? void 0 : _a.length)) {
|
|
38
|
+
return false;
|
|
39
|
+
}
|
|
40
|
+
return this.excludedCapabilities.some((exclusion) => {
|
|
41
|
+
// Check if method matches
|
|
42
|
+
if (exclusion.method !== method) {
|
|
43
|
+
return false;
|
|
44
|
+
}
|
|
45
|
+
// If exclusion has no name requirement, method match is sufficient
|
|
46
|
+
if (!exclusion.name) {
|
|
47
|
+
return true;
|
|
48
|
+
}
|
|
49
|
+
// If exclusion has a name requirement, check if it matches the provided name
|
|
50
|
+
return exclusion.name === name;
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Determines whether a message should be allowed based on authorization policy.
|
|
55
|
+
*
|
|
56
|
+
* @param clientPubkey The client's public key
|
|
57
|
+
* @param message The incoming JSON-RPC message
|
|
58
|
+
* @returns Authorization decision indicating whether the message is allowed
|
|
59
|
+
*/
|
|
60
|
+
authorize(clientPubkey, message) {
|
|
61
|
+
var _a, _b, _c, _d;
|
|
62
|
+
// If no whitelist is configured, allow all messages
|
|
63
|
+
if (!((_a = this.allowedPublicKeys) === null || _a === void 0 ? void 0 : _a.size)) {
|
|
64
|
+
return { allowed: true };
|
|
65
|
+
}
|
|
66
|
+
// Check if the message should bypass whitelisting due to excluded capabilities
|
|
67
|
+
const shouldBypassWhitelisting = ((_b = this.excludedCapabilities) === null || _b === void 0 ? void 0 : _b.length) &&
|
|
68
|
+
(isJSONRPCRequest(message) || isJSONRPCNotification(message)) &&
|
|
69
|
+
this.isCapabilityExcluded(message.method, (_c = message.params) === null || _c === void 0 ? void 0 : _c.name);
|
|
70
|
+
if (this.allowedPublicKeys.has(clientPubkey) || shouldBypassWhitelisting) {
|
|
71
|
+
return { allowed: true };
|
|
72
|
+
}
|
|
73
|
+
// Message is not authorized
|
|
74
|
+
// Only send unauthorized response for requests on public servers
|
|
75
|
+
const shouldReplyUnauthorized = ((_d = this.isPublicServer) !== null && _d !== void 0 ? _d : false) && isJSONRPCRequest(message);
|
|
76
|
+
return { allowed: false, shouldReplyUnauthorized };
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Checks if a client public key is in the allowed whitelist.
|
|
80
|
+
* @param clientPubkey The client's public key
|
|
81
|
+
* @returns true if the client is whitelisted, false otherwise
|
|
82
|
+
*/
|
|
83
|
+
isClientWhitelisted(clientPubkey) {
|
|
84
|
+
var _a;
|
|
85
|
+
if (!((_a = this.allowedPublicKeys) === null || _a === void 0 ? void 0 : _a.size)) {
|
|
86
|
+
return true; // No whitelist means all clients are allowed
|
|
87
|
+
}
|
|
88
|
+
return this.allowedPublicKeys.has(clientPubkey);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
//# sourceMappingURL=authorization-policy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"authorization-policy.js","sourceRoot":"","sources":["../../../../src/transport/nostr-server/authorization-policy.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EACL,iBAAiB,EACjB,gCAAgC,GACjC,MAAM,kCAAkC,CAAC;AAE1C,OAAO,EACL,gBAAgB,EAChB,qBAAqB,GACtB,MAAM,oCAAoC,CAAC;AAgC5C;;;;;;;;GAQG;AACH,MAAM,OAAO,mBAAmB;IAK9B,YAAY,UAAsC,EAAE;QAClD,IAAI,CAAC,iBAAiB,GAAG,OAAO,CAAC,iBAAiB,CAAC;QACnD,IAAI,CAAC,oBAAoB,GAAG,OAAO,CAAC,oBAAoB,CAAC;QACzD,IAAI,CAAC,cAAc,GAAG,OAAO,CAAC,cAAc,CAAC;IAC/C,CAAC;IAED;;;;;OAKG;IACK,oBAAoB,CAAC,MAAc,EAAE,IAAa;;QACxD,oEAAoE;QACpE,IACE,MAAM,KAAK,iBAAiB;YAC5B,MAAM,KAAK,gCAAgC,EAC3C,CAAC;YACD,OAAO,IAAI,CAAC;QACd,CAAC;QAED,IAAI,CAAC,CAAA,MAAA,IAAI,CAAC,oBAAoB,0CAAE,MAAM,CAAA,EAAE,CAAC;YACvC,OAAO,KAAK,CAAC;QACf,CAAC;QAED,OAAO,IAAI,CAAC,oBAAoB,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,EAAE;YAClD,0BAA0B;YAC1B,IAAI,SAAS,CAAC,MAAM,KAAK,MAAM,EAAE,CAAC;gBAChC,OAAO,KAAK,CAAC;YACf,CAAC;YAED,mEAAmE;YACnE,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC;gBACpB,OAAO,IAAI,CAAC;YACd,CAAC;YAED,6EAA6E;YAC7E,OAAO,SAAS,CAAC,IAAI,KAAK,IAAI,CAAC;QACjC,CAAC,CAAC,CAAC;IACL,CAAC;IAED;;;;;;OAMG;IACH,SAAS,CACP,YAAoB,EACpB,OAAuB;;QAEvB,oDAAoD;QACpD,IAAI,CAAC,CAAA,MAAA,IAAI,CAAC,iBAAiB,0CAAE,IAAI,CAAA,EAAE,CAAC;YAClC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;QAC3B,CAAC;QAED,+EAA+E;QAC/E,MAAM,wBAAwB,GAC5B,CAAA,MAAA,IAAI,CAAC,oBAAoB,0CAAE,MAAM;YACjC,CAAC,gBAAgB,CAAC,OAAO,CAAC,IAAI,qBAAqB,CAAC,OAAO,CAAC,CAAC;YAC7D,IAAI,CAAC,oBAAoB,CACvB,OAAO,CAAC,MAAM,EACd,MAAA,OAAO,CAAC,MAAM,0CAAE,IAA0B,CAC3C,CAAC;QAEJ,IAAI,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,YAAY,CAAC,IAAI,wBAAwB,EAAE,CAAC;YACzE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;QAC3B,CAAC;QAED,4BAA4B;QAC5B,iEAAiE;QACjE,MAAM,uBAAuB,GAC3B,CAAC,MAAA,IAAI,CAAC,cAAc,mCAAI,KAAK,CAAC,IAAI,gBAAgB,CAAC,OAAO,CAAC,CAAC;QAE9D,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,uBAAuB,EAAE,CAAC;IACrD,CAAC;IAED;;;;OAIG;IACH,mBAAmB,CAAC,YAAoB;;QACtC,IAAI,CAAC,CAAA,MAAA,IAAI,CAAC,iBAAiB,0CAAE,IAAI,CAAA,EAAE,CAAC;YAClC,OAAO,IAAI,CAAC,CAAC,6CAA6C;QAC5D,CAAC;QACD,OAAO,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;IAClD,CAAC;CACF"}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Internal correlation store for NostrServerTransport.
|
|
3
|
+
* Provides O(1) routing for responses and progress notifications.
|
|
4
|
+
*
|
|
5
|
+
* This module is not exported from the public API.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Represents a route for an in-flight request.
|
|
9
|
+
*/
|
|
10
|
+
export interface EventRoute {
|
|
11
|
+
/** The client's public key that originated this request */
|
|
12
|
+
clientPubkey: string;
|
|
13
|
+
/** The original JSON-RPC request ID (before it was replaced with eventId) */
|
|
14
|
+
originalRequestId: string | number;
|
|
15
|
+
/** Optional progress token for this request */
|
|
16
|
+
progressToken?: string;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Options for configuring the CorrelationStore.
|
|
20
|
+
*/
|
|
21
|
+
export interface CorrelationStoreOptions {
|
|
22
|
+
/** Maximum number of event routes to keep in memory */
|
|
23
|
+
maxEventRoutes?: number;
|
|
24
|
+
/** Maximum number of progress token mappings to keep in memory */
|
|
25
|
+
maxProgressTokens?: number;
|
|
26
|
+
/** Callback invoked when an event route is evicted */
|
|
27
|
+
onEventRouteEvicted?: (eventId: string, route: EventRoute) => void;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Internal store for managing request/response correlation and progress routing.
|
|
31
|
+
*/
|
|
32
|
+
export declare class CorrelationStore {
|
|
33
|
+
private readonly eventRoutes;
|
|
34
|
+
private readonly progressTokenToEventId;
|
|
35
|
+
private readonly clientEventIds;
|
|
36
|
+
constructor(options?: CorrelationStoreOptions);
|
|
37
|
+
/**
|
|
38
|
+
* Registers a new event route for an incoming request.
|
|
39
|
+
*
|
|
40
|
+
* @param eventId The Nostr event ID (used as the request ID)
|
|
41
|
+
* @param clientPubkey The client's public key
|
|
42
|
+
* @param originalRequestId The original JSON-RPC request ID
|
|
43
|
+
* @param progressToken Optional progress token for this request
|
|
44
|
+
*/
|
|
45
|
+
registerEventRoute(eventId: string, clientPubkey: string, originalRequestId: string | number, progressToken?: string): void;
|
|
46
|
+
/**
|
|
47
|
+
* Gets the route for a given event ID.
|
|
48
|
+
*
|
|
49
|
+
* @param eventId The Nostr event ID
|
|
50
|
+
* @returns The event route, or undefined if not found
|
|
51
|
+
*/
|
|
52
|
+
getEventRoute(eventId: string): EventRoute | undefined;
|
|
53
|
+
/**
|
|
54
|
+
* Gets the event ID for a given progress token.
|
|
55
|
+
*
|
|
56
|
+
* @param progressToken The progress token
|
|
57
|
+
* @returns The event ID, or undefined if not found
|
|
58
|
+
*/
|
|
59
|
+
getEventIdByProgressToken(progressToken: string): string | undefined;
|
|
60
|
+
/**
|
|
61
|
+
* Removes an event route and its associated progress token mapping.
|
|
62
|
+
*
|
|
63
|
+
* @param eventId The Nostr event ID
|
|
64
|
+
* @returns true if the route was found and removed, false otherwise
|
|
65
|
+
*/
|
|
66
|
+
removeEventRoute(eventId: string): boolean;
|
|
67
|
+
/**
|
|
68
|
+
* Removes all event routes for a specific client.
|
|
69
|
+
* This is called when a session is evicted or closed.
|
|
70
|
+
*
|
|
71
|
+
* @param clientPubkey The client's public key
|
|
72
|
+
* @returns The number of routes removed
|
|
73
|
+
*/
|
|
74
|
+
removeRoutesForClient(clientPubkey: string): number;
|
|
75
|
+
/**
|
|
76
|
+
* Checks if an event route exists.
|
|
77
|
+
*
|
|
78
|
+
* @param eventId The Nostr event ID
|
|
79
|
+
* @returns true if the route exists, false otherwise
|
|
80
|
+
*/
|
|
81
|
+
hasEventRoute(eventId: string): boolean;
|
|
82
|
+
/**
|
|
83
|
+
* Checks if a progress token mapping exists.
|
|
84
|
+
*
|
|
85
|
+
* @param progressToken The progress token
|
|
86
|
+
* @returns true if the mapping exists, false otherwise
|
|
87
|
+
*/
|
|
88
|
+
hasProgressToken(progressToken: string): boolean;
|
|
89
|
+
/**
|
|
90
|
+
* Gets the current number of event routes.
|
|
91
|
+
*/
|
|
92
|
+
get eventRouteCount(): number;
|
|
93
|
+
/**
|
|
94
|
+
* Gets the current number of progress token mappings.
|
|
95
|
+
*/
|
|
96
|
+
get progressTokenCount(): number;
|
|
97
|
+
/**
|
|
98
|
+
* Clears all event routes and progress token mappings.
|
|
99
|
+
*/
|
|
100
|
+
clear(): void;
|
|
101
|
+
}
|
|
102
|
+
//# sourceMappingURL=correlation-store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"correlation-store.d.ts","sourceRoot":"","sources":["../../../../src/transport/nostr-server/correlation-store.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,2DAA2D;IAC3D,YAAY,EAAE,MAAM,CAAC;IACrB,6EAA6E;IAC7E,iBAAiB,EAAE,MAAM,GAAG,MAAM,CAAC;IACnC,+CAA+C;IAC/C,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED;;GAEG;AACH,MAAM,WAAW,uBAAuB;IACtC,uDAAuD;IACvD,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,kEAAkE;IAClE,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,sDAAsD;IACtD,mBAAmB,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,KAAK,IAAI,CAAC;CACpE;AAED;;GAEG;AACH,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAuB;IACnD,OAAO,CAAC,QAAQ,CAAC,sBAAsB,CAAmB;IAC1D,OAAO,CAAC,QAAQ,CAAC,cAAc,CAA2B;gBAE9C,OAAO,GAAE,uBAA4B;IA8BjD;;;;;;;OAOG;IACH,kBAAkB,CAChB,OAAO,EAAE,MAAM,EACf,YAAY,EAAE,MAAM,EACpB,iBAAiB,EAAE,MAAM,GAAG,MAAM,EAClC,aAAa,CAAC,EAAE,MAAM,GACrB,IAAI;IAsBP;;;;;OAKG;IACH,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,UAAU,GAAG,SAAS;IAItD;;;;;OAKG;IACH,yBAAyB,CAAC,aAAa,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAIpE;;;;;OAKG;IACH,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO;IAyB1C;;;;;;OAMG;IACH,qBAAqB,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM;IAuBnD;;;;;OAKG;IACH,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO;IAIvC;;;;;OAKG;IACH,gBAAgB,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO;IAIhD;;OAEG;IACH,IAAI,eAAe,IAAI,MAAM,CAE5B;IAED;;OAEG;IACH,IAAI,kBAAkB,IAAI,MAAM,CAE/B;IAED;;OAEG;IACH,KAAK,IAAI,IAAI;CAId"}
|